2011-11-04 67 views
4

请对this answer发表评论:无法初始化成员 - 是否可以?

班级成员按其申报顺序进行初始化。通过这个逻辑,下面的构造应该调用未定义行为:

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

我相信UB的原因是检测这种情况的硬度。你也可以解引用NULL,你不能指望一个编译器在你用你的代码犯的任何错误上给你警告和错误。有时需要一个常识。 – littleadv

+1

我不相信它的定义。假设'Bar'有一个不平凡的构造函数;显然,在构造“b”之前调用了'b.operator =()'。但我不确定。 – ephemient

+0

'b'在'a'之前被初始化,还是仅仅被分配到'a'之前? –

回答

4

给定一个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 

其他编译器”吨似乎在乎,虽然...

+0

的Visual C++ 9.0(2008)警告或相同的实现提供以下输出 酒吧2构建的 酒吧1构建 酒吧-858993460从1 – sarat

+0

非常好,感谢分配! –