Читаю книгу С. Липпмана «Внутри объектной модели с ++», есть ли такой код
class Foo { public: int val; Foo *pnext; };
void foo_bar()
{
// Oops: program needs bar's members zeroed out
Foo bar;
Foo* baz = new Foo(); // this line i added myself
if ( bar.val || bar.pnext )
// ... do something
// ...
}
и это говорит о том, что
Msgstr «Конструктор по умолчанию не синтезируется для этого фрагмента кода.
Глобальные объекты гарантированно обнуляют свою связанную память при запуске программы. Местные объекты
размещенные в программном стеке, а объекты кучи, расположенные в хранилище, не имеют связанной памяти
обнуляется; скорее память сохраняет произвольную битовую комбинацию своего предыдущего использования. «
В этом коде объект baz был создан в куче, и согласно тому, что было сказано выше, этот объект не является глобальным и не будет называться конструктором по умолчанию. Я правильно понимаю?
Скобки в new Foo()
уточнить инициализация значения; это в основном означает, что каждый элемент инициализируется нулями. Если вместо этого вы сказали new Foo
, тогда члены останутся неинициализированными, как и для вашей автоматической переменной.
К сожалению, чтобы инициализировать значение автоматической переменной, вы не можете написать Foo bar()
, так как это объявляет функцию. Тебе понадобиться
Foo bar{}; // C++11
Foo bar = Foo(); // Historical C++
Когда вы делаете это:
Foo* baz = new Foo();
вы динамически распределяете Foo
экземпляр и Значение инициализации Это. Для POD это означает, что члены инициализируются нулями. Если вы сказали это (предполагая неглобальный контекст):
Foo* baz = new Foo;
тогда Foo
экземпляр будет инициализирован по умолчанию, что будет означать, что инициализация его членов не выполняется, поскольку они являются POD.
Это также относится к автоматическим хранилищам:
Foo f0; // default initializaiton: members not zeroed out.
Foo f1 = Foo(); // value initialization: members zeroed out.
Foo f2{}; // C++11 value initialization: members zeroed out.
Foo f3(); // Ooops! Function declaration. Something completely different.
Если у класса нет конструктора по умолчанию (и нет другого конструктора), компилятор создаст его для вас. Это должно произойти, иначе вы не сможете создавать экземпляры класса. Однако сгенерированный конструктор по умолчанию ничего не сделает.
Что добавить пустой набор скобок в new Foo()
делает, это значение инициализирует выделенный объект, что означает, что члены инициализируются к их значениям «по умолчанию», что равно нулю для целочисленных значений и значений с плавающей запятой, и nullptr
для указателей.