alfC
alfC

Reputation: 16272

Can lifetime of objects in a initializer list be extended?

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

Answers (1)

rafix07
rafix07

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

Related Questions