Reputation: 9801
The following code works and it doesn't look like it's offering some bad or unwanted behaviour, like undefined behaviour or an incorrect result. The code works as expected, my point is: why ?
std::vector<char> v{std::istreambuf_iterator<char>{
std::ifstream{"yourFile.txt", std::ios::in}.rdbuf()},
std::istreambuf_iterator<char>{}};
this is a call to the constructor of std::vector
that works with iterators, my point is about the lifetime of that rdbuf()
call, and the fact that rdbuf
is a pointer not an object, you can't just copy rdbuf
and pretend that it will always reach the content of your file, nor you can really copy the entire content of the file without using iterators.
What I was expecting is :
ifstream
objectrdbuf
rdbuf
is now inside the constructor of the istreambuf_iterator
and the ifstream
object is gonestd::vector
should now use a copy of a pointer to an object that doesn't exist anymoreI'm surprised that this thing works, someone can illustrate why I'm wrong and what is happening step by step ? The ifstream
object shouldn't be RAII compliant and present only in the scope of the istreambuf_iterator
?
Upvotes: 0
Views: 183
Reputation: 42564
Temporary objects (when not lifetime-extended by binding to a reference) are destroyed at the end of the enclosing full-expression (C++11 12.2/3):
When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1, 12.8), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.
Per 1.9/10:
A full-expression is an expression that is not a subexpression of another expression. [ Note: in some contexts, such as unevaluated operands, a syntactic subexpression is considered a full-expression (Clause 5). —end note ] If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition. A call to a destructor generated at the end of the lifetime of an object other than a temporary object is an implicit full-expression. Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.
Your declaration of v
"produces an implicit call of a function": the two-iterator vector constructor. It is therefore considered to be a full-expression, so the temporary ifstream
object - not to mention the two temporary std::istreambuf_iterator<char>
objects - is not destroyed until after the constructor call completes.
Upvotes: 3