Объект, созданный в куче, не является глобальным?

Читаю книгу С. Липпмана "Внутри с ++ объектная модель", есть ли такой код

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
// ...
}

и он говорит, что "конструктор по умолчанию не синтезируется для этого фрагмента кода.

Глобальные объекты гарантированно обнуляют свою связанную память при запуске программы. Локальные объекты, размещенные в программном стеке, и объекты кучи, расположенные в свободном хранилище, не обнуляют связанную с ними память; скорее память сохраняет произвольную комбинацию битов своего предыдущего использования."

В этом коде объект baz был создан в куче, и в соответствии с тем, что было сказано выше, этот объект не является глобальным и не будет называться конструктором по умолчанию. Я правильно понимаю?

3 ответа

Решение

Скобки в 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 для указателей.

Другие вопросы по тегам