C++ 类成员作为对另一个成员的引用:赋值运算符中的崩溃

C++ 类成员作为对另一个成员的引用:赋值运算符中的崩溃,c++,reference,class-members,C++,Reference,Class Members,我有一个类Bar,其中一个成员Bar::foo: 首先初始化工会成员,否则这是IIRC未定义的行为。然后还可以初始化对工会成员的引用。首先初始化工会成员,否则这是IIRC未定义的行为。然后,您也可以初始化对工会成员的引用。这合法吗 不,因为匿名结构是不合法的。如果您命名它,它将调用未定义的行为,除非首先正确初始化了foo,特别是如果您初始化了数据,则无法读取x和y成员 一旦我解决了所有这些问题,这还会导致什么其他问题 首先,拥有任何类型的引用成员都会抑制赋值运算符的生成。这对你来说可能重要,也可

我有一个类Bar,其中一个成员Bar::foo:


首先初始化工会成员,否则这是IIRC未定义的行为。然后还可以初始化对工会成员的引用。

首先初始化工会成员,否则这是IIRC未定义的行为。然后,您也可以初始化对工会成员的引用。

这合法吗

不,因为匿名结构是不合法的。如果您命名它,它将调用未定义的行为,除非首先正确初始化了foo,特别是如果您初始化了数据,则无法读取x和y成员

一旦我解决了所有这些问题,这还会导致什么其他问题

首先,拥有任何类型的引用成员都会抑制赋值运算符的生成。这对你来说可能重要,也可能不重要。然后,编译器生成的复制构造函数会咬你:它只是盲目地复制所有成员,以foo成员的副本和引用原始对象的foo的引用成员结束。如果原始对象的生命周期较短,则会发生不好的事情。您可能希望编写一个复制构造函数,或者考虑没有参考成员的替代设计。

< P>这是合法的吗?< /P> 不,因为匿名结构是不合法的。如果您命名它,它将调用未定义的行为,除非首先正确初始化了foo,特别是如果您初始化了数据,则无法读取x和y成员

一旦我解决了所有这些问题,这还会导致什么其他问题



首先,拥有任何类型的引用成员都会抑制赋值运算符的生成。这对你来说可能重要,也可能不重要。然后,编译器生成的复制构造函数会咬你:它只是盲目地复制所有成员,以foo成员的副本和引用原始对象的foo的引用成员结束。如果原始对象的生命周期较短,则会发生不好的事情。您可能希望编写一个复制构造函数,或者考虑没有参考成员的替代设计。

我不认为C++中允许使用未命名的结构。无论如何,这看起来像是可怕的,可怕的代码,完全违背了C++和OO的精神。@ KerrekSB:你是对的,G+拒绝代码。你能想象我贴出一个答案并接受它吗-@KerrekSB哦,我原以为它们在C++11中是允许的,但似乎只有匿名工会是允许的。谢谢你的注意。@ KeRek SB——有人会说典型的OO风格很可怕:我看不出他的代码有什么太差。我认为C++中不允许使用未命名的结构。无论如何,这看起来像是可怕的,可怕的代码,完全违背了C++和OO的精神。@ KerrekSB:你是对的,G+拒绝代码。你能想象我贴出一个答案并接受它吗-@KerrekSB哦,我原以为它们在C++11中是允许的,但似乎只有匿名工会是允许的。谢谢你的留言。@Kerrek SB-有人可能会说典型的OO风格很可怕:我在他的代码中没有看到太糟糕的东西。谢谢你的回答,你可能走对了方向。我在类中添加了copyctor和assignment操作符,类似于我在代码中遇到的崩溃。它是否为复制提供了正确的语义?对我来说似乎还可以。您应该进行更多的调试:还有其他事情正在进行。尝试在一个小示例中隔离同一个问题,以了解问题的根源。我将崩溃隔离为几行代码,并将其放入原始帖子中,包括调试器的回溯。感谢您提供了一个好的答案,您可能已经走上了正确的轨道。我在类中添加了copyctor和assignment操作符,类似于我在代码中遇到的崩溃。它是否为复制提供了正确的语义?对我来说似乎还可以。您应该进行更多的调试:还有其他事情正在进行。尝试在一个小示例中分离出相同的问题,看看源代码是什么。我将崩溃隔离到几行代码中,并将其放入原始帖子中,包括调试器的回溯。创建对统一化数据的引用不是UB,只要该引用没有被实际访问,请纠正我的错误;类似于创建指向未初始化内存块的指针不是UB;您可以稍后在使用指针之前使用数据填充该内存块,但您的代码似乎并没有在任何地方填充该内存块。代码只是定义数据结构和对其进行的一些操作,与使用时将保存的数据无关。创建对统一化数据的引用并不重要,只要引用没有被实际访问,如果我错了,请纠正我;类似于创建指向未初始化内存块的指针不是UB;您可以稍后在使用指针之前用数据填充该内存块,但您的代码似乎并没有在任何地方填充它。代码只是定义数据结构和 它们上的一些操作,与使用时所保存的数据无关。
#include<vector>
#include<algorithm>

struct Foo{
    int x, y;
};

struct Bar{
    Foo foo;
    int &x, &y;
    Bar(): x(foo.x), y(foo.y){}
    // copy constructor and assignment operator
    Bar(const Bar& other): foo(other.foo), x(foo.x), y(foo.y){}
    Bar& operator=(const Bar& other){ foo=other.foo; return *this; }
};

int main(void){
    std::vector<Bar> a, b;
    Bar p; p.x=0; p.y=0;
    a.push_back(p);
    std::copy(a.begin(),a.end(),b.begin());
}
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400b29 in Bar::operator= (this=0x0, other=...) at ref2.cpp:14
14      Bar& operator=(const Bar& other){ foo=other.foo; return *this; }
(gdb) bt
#0  0x0000000000400b29 in Bar::operator= (this=0x0, other=...) at ref2.cpp:14
#1  0x00000000004016a0 in std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m<Bar*, Bar*> (
__first=0x405010, __last=0x405030, __result=0x0) at /usr/include/c++/4.6/bits/stl_algobase.h:329
#2  0x000000000040148d in std::__copy_move_a<false, Bar*, Bar*> (__first=0x405010, __last=0x405030, __result=0x0)
at /usr/include/c++/4.6/bits/stl_algobase.h:384
#3  0x0000000000401157 in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > > > (__first=..., __last=..., 
__result=...) at /usr/include/c++/4.6/bits/stl_algobase.h:422
#4  0x0000000000400cc0 in std::copy<__gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > > > (__first=..., __last=..., __result=...)
at /usr/include/c++/4.6/bits/stl_algobase.h:454
#5  0x00000000004009f4 in main () at ref2.cpp:21