Инициализация членов вышла из строя - это нормально? - PullRequest
4 голосов
/ 04 ноября 2011

Из комментария к этот ответ :

Члены класса инициализируются в порядке их объявления.По этой логике следующий конструктор должен вызывать неопределенное поведение:

struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c) : a(b = c) { }
};

Патентно, мы присваиваем b сначала до инициализации a.Присвоение неинициализированному объекту должно быть UB.Неудивительно, что код «работает» с Bar = int, но если я сделаю Bar тяжелым классом с конструкторами, я вижу, что b действительно инициализируется до a.

(дляДополнительное безумие, мы можем даже сказать Foo(Bar c, Bar d) : a(b = c), b(d) { }, но без предупреждения.)

И все же GCC 4.6.1 не предупреждает об этом.Это приемлемое, четко определенное поведение или это строго неправильно?

1 Ответ

4 голосов
/ 04 ноября 2011

Учитывая Bar, где неинициализированное состояние действительно имеет значение для оператора присваивания, я получаю предупреждения от GCC:

#include <iostream>
struct Bar {
    int n;
    Bar(int v) : n(v) {
            std::cout << "Bar " << n << " constructed\n";
    }
    Bar& operator=(const Bar& other) {
        std::cout << "Bar " << n << " assigned from " << other.n << "\n";
        n = other.n;
        return *this;
    }
};
struct Foo
{
   Bar a;
   Bar b;

   Foo(Bar c, Bar d) : a(b = c), b(d) { }
};

int main()
{
        Foo f(Bar(1), Bar(2));
}

тест: https://ideone.com/VDZzG

test.cc: In function ‘int main()’:
test.cc:8:32: warning: ‘*((void*)(& f)+4).Bar::n’ is used uninitialized in this function [-Wuninitialized]
test.cc:23:13: note: ‘*((void*)(& f)+4).Bar::n’ was declared here

Другие компиляторы, которые я пробовал, похоже, не заботятся ...

...