Инициализация путаницы - PullRequest
3 голосов
/ 17 января 2010

Не уверен в подходящем названии, но это вытекает из этого обсуждения:

Есть ли в скобках после имени типа разница с новым?

В Visual Studio 2008, когда я запускаю следующий код:

struct Stan
{
    float man;
};

int main()
{
    Stan *s1 = new Stan;
    Stan *s2 = new Stan();

}

Изучая местных жителей, s1 имеет неинициализированное число с плавающей точкой со случайным значением. s2 - это значение, инициализированное до 0.

Однако, если я добавлю строковый элемент данных, float в обоих случаях не будет инициализирован.

struct Stan
    {
            std::string str;
        float man;
    }; 

Однако строка в обоих случаях инициализируется. Я попытался добавить другие не-POD классы вместо строки, но последний случай происходит, только если я добавляю строковый элемент данных. Я понимаю, что добавление строки по-прежнему сохраняет класс POD? Если это не класс POD, то его значение должно быть инициализировано независимо от скобок, верно? Любые идеи, почему плавающие (и другие примитивные типы данных в этом отношении) не инициализируются, когда я добавляю строковый элемент данных?

Ответы [ 2 ]

5 голосов
/ 17 января 2010

Добавление строки предотвращает превращение структуры в класс POD, поскольку класс POD должен быть агрегатным классом без членов типа, не являющегося POD-структурой, и std::string имеет (среди прочего) объявленные пользователем конструкторы, что делает его не POD-структура.

Это известная ошибка / функция Visual Studio 2008. Она не поддерживает инициализацию значения C ++ 03 для типов, не относящихся к POD, таких как структура во втором примере.

Со структурой, как в вашем втором примере, должно произойти, что значение с плавающей запятой не инициализируется new Stan, но инициализируется нулем в new Stan().

Типы с объявленным пользователем конструктором по умолчанию инициализируются путем вызова этого конструктора во всех случаях, это происходит правильно.

См. здесь и здесь .

0 голосов
/ 17 января 2010

Поведение, которое вы наблюдаете, является соответствующим поведением с точки зрения спецификации языка C ++ 98.

Тип в вашем первом примере - это так называемый тип POD (Plain Old Data). Когда вы применяете инициализатор () к типу класса POD, он выполняет инициализацию с нуля всех членов данных класса.

Тип во втором примере не является типом POD (из-за не члена POD str). Когда вы применяете инициализатор () к типу класса, отличному от POD, он просто вызывает конструктор класса для выполнения инициализации. В вашем случае неявный [предоставленный компилятором] конструктор будет правильно инициализировать член str, но не будет ничего делать для члена man, поэтому вы видите в нем мусор.

Опять же, это правильное поведение в C ++ 98. Это было изменено в C ++ 03. В C ++ 03 инициализатор () будет выполнять значение-инициализацию . В соответствии с правилами инициализации значения, во втором примере поле man также должно инициализироваться нулями в ответ на () initializer.

См. Также https://stackoverflow.com/questions/1976185/what-is-the-difference-between-new-myclass-vs-new-myclass для более подробного объяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...