jeudi 18 août 2016

Lifetime of temporary objects during list-initialization

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]<<"\n";
  std::cout<<" Vector: "<<vec[0]<<", "<<vec[1]<<"\n";
}

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 live-time 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.

One more question: What is the reason behind this exception - why it is better than keeping all temporaries alive until the end, as the std::vector does?

Aucun commentaire:

Enregistrer un commentaire