2010-08-06 1 views
1
class someClass 
{ 
public: 
    int* ptr2Int; 
}; 

Действительно ли это допустимый класс (да, он компилируется)? Если присваивается значение ptr2Int до разыменования его, гарантирован ли класс работать так, как можно было бы ожидать?У классов с неинициализированными указателями есть неопределенное поведение?

+0

Вы ожидаете, что кто-нибудь даст гарантию, что код будет вести себя, как и следовало ожидать, не зная, чего можно ожидать? :) –

ответ

5

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

Имейте в виду, что «опасные способы» использования неинициализированного указателя включают в себя просто попытку прочитать его значение (нет необходимости в разыменовании). Неявные предоставленные компилятором копии-конструктор и операторы присваивания копии, присутствующие в вашем классе, могут выполнить такую ​​попытку, если вы используете эти неявные функции-члены до того, как указатель получит действительное значение.

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

+0

Почему просто чтение неинициализированного указателя «опасно»? – Omnifarious

+0

@Omnifarious: потому что он может содержать так называемое * ловушечное представление *, которое может, например, привести к сбою программы в простой попытке ее прочитать. Фактически, чтение обычного неинициализированного 'int' может привести к тому же. Но с «int» это займет довольно экзотическую платформу. С указателями ловушка гораздо более реальна, поскольку на некоторых аппаратных платформах используются специальные * адресные регистры * для работы с указателями. И эти регистры могут выполнять проверку действительности указателя «на лету». То есть просто загрузка значения в регистр вызывает ловушку. Никакого разыменования не требуется. – AnT

+0

@ Omnifarious: Конечно, более короткий ответ таков: поскольку в спецификации языка четко указано, что чтение неинициализированных значений * любого * типа (за исключением 'unsigned char') обычно приводит к неопределенному поведению. – AnT

1

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

1

Да, это точно так же, как struct с одним неинициализированным указателем, и оба гарантированно будут работать нормально (до тех пор, пока вы установите указатель перед любым его использованием, конечно).

-1

Пока вы не разыщите указатель, все хорошо, тогда это неопределенная территория.

Некоторые компиляторы устанавливают указатели на значения по умолчанию (например, null) в зависимости от того, компилируются ли вы в режиме отладки или выпуска. Таким образом, все может работать в одном режиме, и вдруг все разваливается в другом.

+0

Читая его значение также UB – qdii