Делает ли make_shared инициализацию по умолчанию (zero-init) для каждой переменной-члена
Возьмите обычную структуру (или класс) с типами и объектами Plain Old Data. Обратите внимание, что конструктор по умолчанию не определен.
struct Foo
{
int x;
int y;
double z;
string str;
};
Теперь, если я объявлю экземпляр f в стеке и попытаюсь напечатать его содержимое:
{
Foo f;
std::cout << f.x << " " << f.y << " " << f.z << f.str << std::endl;
}
Результатом являются данные мусора, напечатанные для x, y и z. И строка по умолчанию инициализируется как пустая. Как и ожидалось.
Если я создам экземпляр shared_ptr<Foo>
с помощью make_shared
и распечатать:
{
shared_ptr<Foo> spFoo = make_shared<Foo>();
cout << spFoo->x << " " << spFoo->y << " " << spFoo->z << spFoo->str << endl;
}
Тогда x, y и z все 0
, Что заставляет казаться, что shared_ptr
выполняет инициализацию по умолчанию (нулевая инициализация) для каждого члена после создания экземпляра объекта. По крайней мере, это то, что я наблюдаю с компилятором Visual Studio.
Это стандарт для C++? Или было бы необходимо иметь явный конструктор или явный ={}
оператор после создания, чтобы гарантировать поведение с нулевым инициализацией во всех компиляторах?
2 ответа
Если вы видите, например, это std::make_shared
ссылка вы увидите, что
Объект строится как бы по выражению
::new (pv) T(std::forward<Args>(args)...)
, гдеpv
это внутреннийvoid*
указатель на хранилище, подходящее для хранения объекта типаT
,
Это означает std::make_shared<Foo>()
в основном делает new Foo()
, То есть это значение инициализирует структуру, что приводит к обнулению переменных, не являющихся членами класса.
Чтобы быть более точным, std:: make_shared использует синтаксис инициализации значения,
Объект строится как бы по выражению
::new (pv) T(std::forward<Args>(args)...)
За Foo
с пустым списком инициализаторов, это означает, что все его члены со встроенным типом будут инициализироваться нулями, и std::string
будет инициализирован по умолчанию.