GCC\'s implementation destroys a std::initializer_list
array returned from a function at the end of the return full-expression. Is this correct?
Both te
The wording you refer to in 8.5.4/6 is defective, and was corrected (somewhat) by DR1290. Instead of saying:
The lifetime of the array is the same as that of the
initializer_list
object.
... the amended standard now says:
The array has the same lifetime as any other temporary object (12.2 [class.temporary]), except that initializing an
initializer_list
object from the array extends the lifetime of the array exactly like binding a reference to a temporary.
Therefore the controlling wording for the lifetime of the temporary array is 12.2/5, which says:
The lifetime of a temporary bound to the returned value in a function return statement is not extended; the temporary is destroyed at the end of the full-expression in the return statement
Therefore the noisydt
objects are destroyed before the function returns.
Until recently, Clang had a bug that caused it to fail to destroy the underlying array for an initializer_list
object in some circumstances. I've fixed that for Clang 3.4; the output for your test case from Clang trunk is:
destroyed
destroyed
destroyed
received
destroyed
destroyed
destroyed
received
... which is correct, per DR1290.
std::initializer_list
is not a container, don't use it to pass values around and expect them to persist
DR 1290 changed the wording, you should also be aware of 1565 and 1599 which aren't ready yet.
Then the return value's array should also survive into the calling function, and it should be possible to preserve it by binding it to a named reference.
No, that doesn't follow. The array's lifetime doesn't keep being extended along with the initializer_list
. Consider:
struct A {
const int& ref;
A(const int& i = 0) : ref(i) { }
};
The reference i
binds to the temporary int
, and then the reference ref
binds to it as well, but that doesn't extend the lifetime of i
, it still goes out of scope at the end of the constructor, leaving a dangling reference. You don't extend the underlying temporary's lifetime by binding another reference to it.
Your code might be safer if 1565 is approved and you make il
a copy not a reference, but that issue is still open and doesn't even have proposed wording, let alone implementation experience.
Even if your example is meant to work, the wording regarding lifetime of the underlying array is obviously still being improved and it will take a while for compilers to implement whatever final semantics are settled on.