调整大小后保持对向量元素的引用有效

问题描述 投票:0回答:3

如果我们引用向量元素,然后调整向量的大小,则引用不再有效,迭代器也会发生同样的情况:

std::vector<int> vec{0, 1, 2, 3, 4, 5};
int& ref = vec[0];
auto itr = vec.begin();

cout <<  ref << " " << *itr << endl;

vec[0] = 7;

cout <<  ref << " " << *itr << endl;

vec.resize(100);
vec[0] = 3;

cout <<  ref << " " << *itr << endl;

打印出来:

0 0
7 7
0 0 // We expected a 3 here

而且我知道只保留对向量本身的引用并调用 vec[0] 会更实用,但只是为了提问,是否有可能保留一个始终为 vec[0] 的对象如果物体移动了?

我尝试编写一个小帮助器类来帮助解决此问题,但我不确定这是否是最好的方法,或者它是否会失败?

template<typename T>
struct HelperClass
{
    std::vector<T>& vec;
    size_t element;

    HelperClass(std::vector<T>& vec_, size_t element_) : vec(vec_) , element(element_) {}

    // Either define an implicit conversion from HelperClass to T
    // or a 'dereference' operator that returns vec[0]
    operator T&() { return vec.at(element); }
    T& operator*() { return vec.at(element); }
};

并通过隐式转换为 T& 或通过“取消引用”运算符来使用它:

std::vector<int> vec{0, 1, 2, 3, 4, 5};
int& ref = vec[0];
auto itr = vec.begin();
HelperClass<int> hlp = HelperClass<int>(vec, 0); // HelperClass

cout <<  ref << " " << *itr << " " << hlp << " " << *hlp << endl;

vec[0] = 7;

cout <<  ref << " " << *itr << " " << hlp << " " << *hlp << endl;

vec.resize(100);
vec[0] = 3;

cout <<  ref << " " << *itr << " " << hlp << " " << *hlp << endl;

它已经打印了例外的内容:

0 0 0 0 
7 7 7 7
0 0 3 3

那么,除了使用辅助类之外,是否还有更好的方法来做到这一点?辅助类在某些情况下会不可靠吗?

我也在reddit中遇到过this线程,但似乎他们没有在那里讨论辅助类

c++ vector reference
3个回答
2
投票

您可以做的一件事是拥有一个指针向量而不是一个实例向量。当然,这有其自身的一系列问题,但如果您必须让对象引用在向量调整大小后幸存下来,那就可以了。


1
投票

向量的任何重新分配都会使任何指针、引用和迭代器无效。

在您的示例中,您的

HelperClass
毫无用处,因为:

cout <<  ref << " " << *itr << " " << hlp << " " << *hlp << endl;

等同于:

cout <<  ref << " " << *itr << " " << vec[0] << " " << vec[0] << endl;

如果发生重新分配,只需使用迭代器接口

.begin()
.end()
再次访问迭代器。


0
投票

我认为你可以保留索引,它在调整大小后不应改变。

© www.soinside.com 2019 - 2024. All rights reserved.