包含引用或指针的对象向量
Vector of objects containing references or pointers
我将一些对象存储在vector中。当我调用使用引用的这样一个对象的成员函数时,程序被终止(没有错误)。我编写了以下代码来运行一些测试。似乎在添加元素之后,第一个条目中的引用失败了。为什么会这样,我能做些什么来避免这个问题?当我使用指针而不是引用时,它的行为完全相同。
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(int i) : var(i), ref(var) {}
int get_var() {return var;}
int get_ref() {return ref;}
private:
int var;
int& ref;
};
int main ()
{
vector<A> v;
for(unsigned int i=0;i<=2 ;i++){
v.emplace_back(i+5);
cout<<"entry "<<i<<":"<<endl;
cout<<" var="<<v.at(i).get_var()<<endl;
cout<<" ref="<<v.at(i).get_ref()<<endl;
}
cout<<endl;
for(unsigned int i=0;i<=2 ;i++){
cout<<"entry "<<i<<":"<<endl;
cout<<" var="<<v.at(i).get_var()<<endl;
cout<<" ref="<<v.at(i).get_ref()<<endl;
}
return 0;
}
输出为:
entry 0:
var=5
ref=5
entry 1:
var=6
ref=6
entry 2:
var=7
ref=7
entry 0:
var=5
ref=0 /////////////here it happens!
entry 1:
var=6
ref=6
entry 2:
var=7
ref=7
v has 3 entries
这是因为你对emplace_back的调用导致向量调整大小。为了做到这一点,向量可能需要也可能不需要将整个向量移动到内存中的不同位置。您的"ref"仍然引用旧的内存位置。
这是否实际发生在某种程度上取决于实现;编译器可以自由地为vector保留额外的内存,这样它们就不必每次向vector的后面添加内容时都重新分配内存。
emplace_back:
的标准文档中有提到<迭代器有效性/strong>
如果发生了重新分配,所有的迭代器,指针与此容器相关的引用无效。否则,只有end迭代器失效,其他所有迭代器,对元素的指针和引用保证保持引用
为了避免这个问题,您可以(正如JAB在注释中建议的那样)动态创建引用,而不是将其存储为成员变量:
int& get_ref() {return var;}
…虽然我更愿意用智能指针,而不是这种东西。
或者,如RnMss所建议的,实现复制构造函数,以便在vector复制对象时引用新位置:
A(A const& other) : ref(var) {
*this = other;
}
好的,这就是发生的事情。它确实有助于从内存位置的角度理解对象,并记住vector允许在内存中移动对象。
v.emplace_back(5)
在vector中创建一个a对象。这个对象现在驻留在从0x1234
到0x123C
的内存块中。成员变量var位于0x1234
,成员变量ref位于0x1238
。对于该对象,var的值为0x0005
, ref的值为0x1234
。
向vector中添加元素时,在第二次插入时vector空间耗尽。因此,它调整大小并将当前元素(此时只是第一个元素)从位置0x1234
移动到位置0x2000
。这意味着成员元素也被移动了,所以var现在位于地址0x2000
, ref现在位于地址0x2004
。但是它们的值被复制了,所以var的值仍然是0x0005
, ref的值仍然是0x1234
。
ref指向一个无效的位置(但是var仍然包含正确的值!)尝试访问内存ref现在指向未定义的行为,通常是坏的。
提供对成员属性的引用访问的更典型的方法是:
int & get_ref() {return var;}
将引用作为成员属性本身并没有错误,但是如果你要存储一个对象的引用,你必须确保该对象不会移动。
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 从多个源构造一个对象,包括一个对象向量
- 如何从文件中读取两个字符串和数字数组,并将它们存储在对象向量中
- 对象 C++ 向量的 STL 容器
- 初始化C++中的对象向量
- 从自定义类获取对象向量中的 max 元素
- 如何在 c++ 中打印存档中的对象向量
- 如何将包含另一个对象向量的对象保存到文件中,并使用C++中的二进制文件从文件中读回?
- 尝试重载输出运算符时,我无法遍历对象向量
- 如何在C++中打印对象向量的内容
- 打印出对象向量中的每个元素C++
- 在 c++ 的构造函数中分配对象向量时出错
- 遍历对象向量,并找到与从文本文件中提取的对象匹配的变量
- 对象向量是否在堆或堆栈上分配C++?
- 基于不同字段的对象向量的排序功能
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 用rapidjson读取子对象向量
- 尝试使用比较运算符对对象向量进行排序
- 如何用对象向量重载 cin(>>)
- 如何将某个元素从shared_ptr擦除到对象向量?