C ++: указатель члена инициализирован? - PullRequest
9 голосов
/ 17 июля 2009

Пример кода должен объяснить вещи:

class A
{
    B* pB;
    C* pC;
    D d;

    public : 
    A(int i, int j) : d(j)
    {
        pC = new C(i, "abc");
    } // note pB is not initialised, e.g. pB(NULL)

    ...
};

Очевидно, что pB должен быть явно инициализирован в NULL, чтобы быть безопасным (и очистить), но, как оно есть, каково значение pB после построения A? Является ли оно инициализированным по умолчанию (равным нулю ?) или нет (то есть неопределенный и какой бы то ни было в памяти). Я понимаю, что инициализация в C ++ имеет несколько правил.

Я думаю, это не инициализировано по умолчанию; как запущенный в режиме отладки в Visual Studio, он установил pB, указывающий на 0xcdcdcdcd - что означает, что память была новой (в куче), но не инициализирована. Однако в режиме выпуска pB всегда указывает на NULL. Это просто случайно, и поэтому не следует полагаться; или эти компиляторы инициализируют это для меня (даже если это не в стандарте)? Он также выглядит как NULL при компиляции с помощью компилятора Sun в Solaris.

Я действительно ищу конкретную ссылку на стандарт, чтобы сказать так или иначе.

Спасибо.

Ответы [ 7 ]

11 голосов
/ 17 июля 2009

Вот соответствующий отрывок из стандарта:

12.6.2 Инициализация баз и членов [class.base.init]

4 Если данный элемент нестатических данных или базовый класс не назван в мем-
идентификатор инициализатора в mem-initializer-list, затем

- Если объект является нестатическим член (возможно, квалифицированный как cv) тип класса (или его массив) или базовый класс и класс сущности класс не POD, объект инициализируется по умолчанию ( dcl.init ). Если объект является нестатическим членом данных типа с константой, класс сущности должен иметь объявленный пользователем конструктор по умолчанию.

- В противном случае сущность не является инициализирована . Если субъект квалифицированный const тип или ссылочный тип, или (возможно, cv-quali- тип класса POD (или его массив), содержащий (непосредственно или косвенно) член типа с константой, программа больной- формируется.

После вызова конструктора для класс X завершен, если член

из X не указан ни в mem-инициализаторы конструктора, ни
инициализированный по умолчанию, ни инициализированный при исполнении тела
конструктор, член имеет неопределенное значение.

4 голосов
/ 17 июля 2009

В соответствии с разделом 12.6.2.4 стандарта C ++ 0x , в случае переменной указателя, если вы не включили ее в список инициализатора и не установили ее тело конструктора, то оно имеет неопределенное значение. 0xCDCDCDCD и 0 - два возможных таких значения, как и все остальное. : -)

1 голос
/ 17 июля 2009

Я полагаю, что это артефакт из старых добрых C-дней, когда нельзя было ожидать, что будет в памяти. По мере того, как стандарты переходили на C ++, это «соглашение» поддерживалось. По мере разработки компиляторов C ++ отдельные авторы взяли на себя «решение» этой проблемы. Поэтому ваш пробег может варьироваться в зависимости от выбранного вами компилятора.

«0xcdcdcdcd» выглядит как легко идентифицируемый шаблон, который «помогает» в отладке вашего кода. Вот почему он не отображается в режиме релиза.

Надеюсь, это немного помогло и удачи.

0 голосов
/ 17 июля 2009

Редко я рекомендую не изучать что-либо о языке, который вы используете, но в этом случае, инициализируется ли pB, не является полезной информацией. Просто инициализируйте это. Если он автоматически инициализируется, компилятор оптимизирует дополнительную инициализацию. Если это не так, вы добавили одну дополнительную инструкцию процессора и предотвратили целый ряд потенциальных ошибок.

0 голосов
/ 17 июля 2009

Неинициализированные указатели позволяют в основном содержать случайное значение, хотя некоторые компиляторы имеют тенденцию заполнять их 0 или другим распознаваемым значением, особенно в режиме отладки.

ИМХО, это связано с тем, что в C ++ дизайн "не плати за то, что не используешь". Если вы не считаете это важным, компилятору не нужно тратить деньги на инициализацию переменной для вас. Конечно, после того, как вы погнались за случайным указателем, вы можете найти разумным инициализировать его в следующий раз ...

0 голосов
/ 17 июля 2009

Значение pB не определено. Это может или не может быть последовательно одно и то же значение - обычно зависит от того, что было ранее в том же месте в памяти до выделения конкретного экземпляра A.

0 голосов
/ 17 июля 2009

Неинициализированные указатели могут указывать на что угодно. Некоторые поставщики компиляторов помогут вам и заставят их указывать на 0 или 0xcdcdcdcd или что-либо еще.

Чтобы ваш код был безопасным и переносимым, вы всегда должны инициализировать ваши указатели. либо до 0, либо до действительного значения.

например.

C* pc = 0;

или

C* pc = new C(...);

Если вы всегда инициализируете указатели на 0, тогда это безопасно:

if (!pc) 
    pc = new C(...);

Если вы не инициализируете, у вас не будет способа разграничить инициализированные и неинициализированные указатели.

Кроме того, в C ++ нет такого ключевого слова, как NULL. Большинство компиляторов определяют NULL как 0, но его использование не считается переносимым. В новом стандарте c ++ 0x будет введено новое ключевое слово nullptr, поэтому, когда это выйдет, у нас наконец-то будет портативная константа нулевого указателя.

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