Почему это простое назначение неопределенного поведения? - PullRequest
12 голосов
/ 06 февраля 2012

Я обновлял свое понимание инициализации значения по сравнению с инициализацией по умолчанию и наткнулся на this :

struct C {
    int x;
    int y;
    C () { }
};

int main () {
    C c = C ();
}

Видимо, это UB, потому что

В случае C () есть конструктор, который способен инициализация элементов x и y, поэтому инициализация не происходит. Поэтому попытка скопировать C () в c приводит к неопределенному поведению.

Я думаю, что понимаю почему, но я не уверен. Может кто-нибудь уточнить, пожалуйста?

Означает ли это, что это также UB?

int x; x = x;

Кстати, что касается инициализации значения, гарантируется ли следующее значение равным нулю?

int x = int ();

Ответы [ 3 ]

13 голосов
/ 06 февраля 2012

Ваш первый пример имеет неопределенное поведение, потому что по умолчанию конструктор копирования, сгенерированный компилятором, будет выполнять копирование по элементам, int s может иметь значения перехвата, а чтение значения перехвата для его копирования может вызвать сбой программы.

На практике, я не могу представить, чтобы это когда-либо действительно рухнуло;компилятор почти наверняка оптимизирует копию, и даже если этого не произойдет, он, скорее всего, будет использовать специальную побитовую копию, которая будет копировать, не проверяя значения перехвата.(В C ++ вы гарантированно сможете копировать байты.)

Во втором случае, опять же, неопределенное поведение.Хотя в этом случае у вас есть назначение, а не конструкция копирования, и компилятор с меньшей вероятностью его оптимизирует.(В первом примере назначения нет, только конструкция копирования.)

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

1 голос
/ 06 февраля 2012

Я не думаю, что это на самом деле undefined behavior, хотя значения в c имеют unspecified values.То есть поведение программы хорошо определено, если вы не используете эти неопределенные значения.Если вы используете их, например, в условии или для их печати, результаты не будут определены.Однако я не думаю, что программе разрешено делать что-то странное.

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

0 голосов
/ 06 февраля 2012

Нет. Что произойдет, так это то, что большинство компиляторов оптимизируют настройку переменной out, но те, которые этого не делают, просто не изменят значение x. Это так же, как следующий код:

int x = 0;
x = 0;

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

...