Reputation: 16272
I have the impression that std::initializer_list
might behave like literal strings in C++, and even further they might extend the lifetime of const references. Is that a correct assessment?
Can objects in an initializer_list
be somehow referenced later (without copying them), in local scope? in global scope?
For example this tests pass in GCC and clang. Is that just fortuitous?
#include<cassert>
#include<initializer_list>
struct A{
double const* p;
A(std::initializer_list<double> il){ p = &*(il.begin() + 1); };
};
double f(){return 5.;}
int main(){
A a1{1.,2.,3.};
assert( *a1.p == 2. );
A a2{1., f(), f()};
assert( *a2.p == 5. );
}
Upvotes: 4
Views: 740
Reputation: 20936
This is undefined behaviour.
In your case initializer_list
refers to temporary array const double[3]
, the lifetime of this array is described as below:
ref The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended. [until c++14]
The lifetime of the underlying array is the same as any other temporary object [since c++14]
and
ref All temporary objects are destroyed as the last step in evaluating the full-expression
so in your case when constructor of A
is called, temporary array with 3 doubles is created, then you are taking address of elements of temporary array and when constructor ends temporary array is destroyed (in this case the full expression is the call of ctor), so as a result p
is dangling poiner.
Upvotes: 7