c++ - 包含引用或指针的对象 vector

标签 c++ pointers vector reference

我将一些对象存储在一个 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 的调用导致 vector 调整大小。为了做到这一点, vector 可能需要也可能不需要将整个 vector 移动到内存中的不同位置。您的“ref”仍在引用旧的内存位置。

这是否真的发生在某种程度上取决于实现;编译器可以自由地为 vector 保留额外的内存,这样它们就不必在每次向后面添加内容时都重新分配。

emplace_back 的标准文档中提到了它:

Iterator validity

If a reallocation happens, all iterators, pointers and references related to this container are invalidated. Otherwise, only the end iterator is invalidated, and all other iterators, pointers and references to elements are guaranteed to keep referring to the same elements they were referring to before the call.

为了避免这个问题,您可以(正如 JAB 在评论中建议的那样)即时创建引用而不是将其存储为成员变量:

int& get_ref() {return var;}

...虽然我更愿意使用智能指针而不是这种东西。

或者,如 RnMss 所建议的那样,实现复制构造函数,以便在对象被 vector 复制时引用新位置:

A(A const& other) : ref(var) {
    *this = other;
}

关于c++ - 包含引用或指针的对象 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22669567/

相关文章:

c - 指针和虚拟内存

c++ - if 语句中有 float 的奇怪错误

c++ - 是否有可在 Visual Studio 中编译的可用和许可版本的 strptime.h?

C++11 原子 x86 内存排序

C-将子链表传递给函数

C::在函数中转换指针会丢失数据吗?

actionscript-3 - ActionScript - 比较和删除复杂数组的重复项?

c++ - 从列表 vector 中删除元素 C++

c++ - 这两个 std::vector 的赋值方法有什么区别?

c++:有界数字的异构模板