J'ai toujours supposé, que les objets temporaires vivre jusqu'à la fin d'une expression. Voici cependant une curieuse différence entre les initialisations d'un std::vector
et un tableau.
Veuillez considérez le code suivant:
#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";
}
La sortie de ce programme est un peu (au moins pour moi) inattendu:
Array: 1, 1
Vector: 1, 2
Cela signifie que les objets temporaires sont vivants au cours de l'ensemble de l'initialisation de l' std::vector
, mais ils sont créés et détruits l'un après l'autre dans le cas d'un tableau. J'attendrais la temporaires à vivre jusqu'à ce que la pleine expression int arr[]{ID().id, ID().id};
est terminée.
La norme mentionne qu'une seule exception concernant la durée de vie des objets temporaires et de l'initialisation de tableaux (12.2). Cependant je ne comprends pas son sens et ne sais pas pourquoi il est appliqué dans ce cas particulier:
Il y a deux contextes dans lesquels temporaires sont détruits dans un autre point qu'à la fin de l'expression. Le premier contexte c'est quand un constructeur par défaut est appelé à initialiser un élément d'une tableau. Si le constructeur a un ou plusieurs arguments par défaut, l' la destruction de chaque temporaire créé dans un argument par défaut est séquencée avant la construction de la prochaine élément de tableau, le cas échéant.
Aperçu des résultats avec différents compilateurs (MSVS résultat est un curtesy de 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
Comme ecatmur a souligné, pour l'ensemble de l'initialisation de chaque élément de l'arc-boutée-init-liste est une expression, donc le code suivant
struct S{
int a;
int b;
} s{ID().id, ID().id};
std::cout<<" Struct: "<<s.a<<", "<<s.b<<"\n";
doit imprimer Struct 1, 1
à la console. C'est exactement ce que le programme compilé par g++. Cependant, clang semble avoir un bug - le programme qui imprime Struct 1, 2
.
Un bug a été signalé à clang: https://llvm.org/bugs/show_bug.cgi?id=29080