Я всегда предполагал, что временные объекты живут до конца полного выражения. Здесь, однако, любопытная разница между инициализацией a std::vector
и массивом.
Обратите внимание на следующий код:
#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";
}
Результат этой программы немного (по крайней мере для меня) неожиданно:
Array: 1, 1
Vector: 1, 2
Это означает, что временные объекты являются живыми во время всей инициализации std::vector
, но они создаются и разрушаются один за другим в случае массива. Я ожидал бы, что временные данные будут жить до тех пор, пока полное выражение int arr[]{ID().id, ID().id};
не будет завершено.
В стандарте упоминается одно исключение в отношении времени жизни временных объектов и инициализации массивов (12.2). Однако я не понимаю его смысла и не знаю, почему он применяется в этом конкретном случае:
Существует два контекста, в которых временные другая точка, чем конец полного выражения. Первый контекст когда вызывается конструктор по умолчанию для инициализации элемента массив. Если конструктор имеет один или несколько аргументов по умолчанию, уничтожение каждого временного объекта, созданного в аргументе по умолчанию, секвентированный до построения следующего элемента массива, если он есть.
Обзор результатов с разными компиляторами (результат MSVS является репрезентацией 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
Как указывал ecatmur, для агрегатной инициализации каждый элемент списка бит-init-это полное выражение, поэтому следующий код
struct S{
int a;
int b;
} s{ID().id, ID().id};
std::cout<<" Struct: "<<s.a<<", "<<s.b<<"\n";
должен печатать Struct 1, 1
на консоли. Это именно то, что делает программа, скомпилированная g++. Тем не менее, у clang, похоже, есть ошибка - итоговая программа выводит Struct 1, 2
.
Сообщалось об ошибке: https://llvm.org/bugs/show_bug.cgi?id=29080