I always assumed, that temporary objects live until the end of a full-expression. Here is however a curious difference between initializations of a std::vector
and an array.
Please consider the following code:
#include <iostream>
#include <vector>
struct ID{
static int cnt;
// the number of living object of class ID at the moment of creation:
int id;
ID():id(++cnt){}
~ID(){
cnt--;
}
};
int ID::cnt=0;
int main(){
int arr[]{ID().id, ID().id};
std::vector<int> vec{ID().id, ID().id};
std::cout<<" Array: "<<arr[0]<<", "<<arr[1]<<"
";
std::cout<<" Vector: "<<vec[0]<<", "<<vec[1]<<"
";
}
The output of this program is a little bit (at least for me) unexpected:
Array: 1, 1
Vector: 1, 2
That means, the temporary objects are alive during the whole initialization of the std::vector
but they are created and destructed one after each other in the case of an array. I would expect the temporaries to live until the full-expression int arr[]{ID().id, ID().id};
is completed.
The standard mentions one exception concerning the lifetime of temporary objects and initialization of arrays (12.2). However I don't get its meaning and don't know why it is applied in this particular case:
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array. If the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any.
Overview of the results with different compilers (MSVS result is a curtesy of NathanOliver):
Array Vector
clang 3.8 1, 2 1, 2
g++ 6.1 1, 1 1, 2
icpc 16 1, 1 1, 2
MSVS 2015 1, 1 1, 2
As ecatmur pointed out, for aggregate initialization every element of the braced-init-list is a full-expression, thus the following code
struct S{
int a;
int b;
} s{ID().id, ID().id};
std::cout<<" Struct: "<<s.a<<", "<<s.b<<"
";
should print Struct 1, 1
to the console. That is exactly what the program compiled by g++ does. However, clang seems to have a bug - the resulting program prints Struct 1, 2
.
A bug has been reported to clang: https://llvm.org/bugs/show_bug.cgi?id=29080
question from:https://stackoverflow.com/questions/39025342/lifetime-of-temporary-objects-during-list-initialization