#include <iostream>
#include <vector>
class myClass {
public:
double a;
double& ref;
myClass() : ref(a)
{
a = 1;
}
~myClass() {}
};
using namespace std;
int main()
{
vector<myClass> myVector;
int nIter = 5;
while (nIter--) {
myVector.push_back(myClass());
}
return 0;
}
嗨。
我有myClass,我想将myClasses推回去,然后将它们组合到一个向量中。 但不幸的是, 我必须在myClass中使用引用。 问题是当临时对象销毁时,引用变为无效,并且向量包含其引用无效的对象。 经过研究,我能够看到那些引用变量指向(引用)相同的内存。 我想找到每个向量元素的引用成员变量引用每个向量元素的a(成员变量)的方式。 有什么办法可以做到这一点..?
答案 0 :(得分:2)
之所以会出现这种现象,是因为您正在将'ref'成员初始化为堆栈中的值,然后默认的复制构造函数会将其复制到向量中。
例如,在调试器中,给ref的值是:
+ &myVector[1].ref 0x00eff80c {2.0000000000000000} double *
+ &myVector[1] 0x00126940 {a=2.0000000000000000 ref=2.0000000000000000 }
+ myVector { size=0x00000002 } std::vector<myClass,std::allocator<myClass> >
+ &nIter 0x00eff8f0 {0xffffffff} int *
您可以看到myVector[1].ref
不在您期望的myVector[1]
内部,并且实际上位于堆栈中。您可以看到nIter和ref仅相距57个字节:
&nIter - (int*)&myVector[0].ref 57
如果您想了解隐式发生的情况,可以删除副本构造函数:
myClass(myClass const &rhs) = delete;
在myClass内部,您会在push_back上收到错误消息。
另一种选择是编写自己的副本构造函数:
myClass(myClass const &rhs) : ref(a) {
a = rhs.a;
}
如果您对此进行调试,则会看到值正确,并且每个引用的内存位置现在都位于myClass对象的范围之内。
最后,您也许可以使用emplace_back
代替push_back
,这将直接在向量的内存中构造myClass
而不是调用复制ctor,尽管我不建议这样做因为它留下了这个引用复制错误。
如果走复制ctor路线,也不要忘记赋值运算符: https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
例如
myClass baz;
baz = myVector[0];
这将调用operator =而不是复制ctor。如果您声明副本ctor,我的编译器(最新的Visual Studio c ++)会自动删除operator =,因此可以捕获此错误,但是编译器可能不会。