C ++:指针向量在push_back()之后丢失引用 [英] C++: vector of pointer loses the reference after push_back()

查看:137
本文介绍了C ++:指针向量在push_back()之后丢失引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,有一个Node对象的全局向量和一个Node指针的局部向量:

#include<cstdio>
#include<cstdlib>
#include<vector>

using namespace std;

class Node {
    int n;

public:
    Node(int i) : n(i);
    int getN() { return n; }
};

vector<Node> v;

int main() {
    vector<Node*> p;
    v.push_back(Node(1));
    p.push_back(&v[0]);
    printf("first node id : %d\n", (*p[0]).getN());

    return 0;
}

我在全局向量&中插入了一个节点对象在本地向量中插入了该对象的指针.我上面的代码的输出是:

first node id : 1

但是,如果我将主要功能更改为此:

int main()
{
    vector<Node*> p;
    v.push_back(Node(1));
    p.push_back(&v[0]);
    v.push_back(Node(2));
    p.push_back(&v[1]);
    printf("first node id : %d\n", (*p[0]).getN());

    return 0;
}

代码显示一个垃圾值:

first node id : 32390176

我不知道问题所在. vector数据结构在插入后是否会更改每个对象的引用? 我该如何解决?

解决方案

向量在插入后是否会更改引用?"

可能,是的. std::vector 可能会在您添加/其他元素,使所有指针无效:

迭代器[读取:指针]无效

(用于操作)push_backemplace_back ...如果矢量更改了容量,则所有这些[即所有迭代器均无效].如果不是,则仅end().

我该如何解决?"

如果向量的容量由于插入而没有改变,则上述无效规则将不适用-因为向量不会不必要地重新分配存储空间.因此,如果在示例中将向量的容量预先设置为2(例如,使用v.reserve(2)),则指针将保持有效.如果您事先不知道大小,但是可以延迟第二个向量的构造(使用指针),则不必保留,只需在插入最后一个元素后再获得大小即可.

但是,上述方法高度不推荐.如果要使向量恒定(至少在要构造和使用第二个向量的函数范围内),则将有很强的保证不会重新分配.或者,如果可以提前确定大小,则可以使用 std::array ,在该容器的存储中使用指针会更合适:

迭代器无效

通常,数组的迭代器在数组的整个生命周期内都不会失效.

您还可以考虑将 indices 存储到向量中(尽管在那里,向量可能会缩小,使索引无效,或者您可能会在中间插入元素等).

无论如何,我怀疑您实际上可能不想做任何事情,也就是说,对于一个可以用另一种方法完全解决的问题来说,这似乎不是一个很好的解决方案.

PS-如果向量具有自定义分配器,则我编写的所有内容可能都不相关. /sub>

In my code a have a global vector of Node object and a local vector of Node pointers:

#include<cstdio>
#include<cstdlib>
#include<vector>

using namespace std;

class Node {
    int n;

public:
    Node(int i) : n(i);
    int getN() { return n; }
};

vector<Node> v;

int main() {
    vector<Node*> p;
    v.push_back(Node(1));
    p.push_back(&v[0]);
    printf("first node id : %d\n", (*p[0]).getN());

    return 0;
}

I inserted a node object to global vector & inserted the pointer of that object in the local vector. Output of my above code is:

first node id : 1

However, if I change my main function to this:

int main()
{
    vector<Node*> p;
    v.push_back(Node(1));
    p.push_back(&v[0]);
    v.push_back(Node(2));
    p.push_back(&v[1]);
    printf("first node id : %d\n", (*p[0]).getN());

    return 0;
}

The code prints a garbage value:

first node id : 32390176

I can't figure out the problem. Does the vector data structure changes the references of each object after an insertion ? How can I fix this ?

解决方案

"Does a vector change the references after an insertion?"

Possibly, yes. An std::vector may reallocate its (heap) storage when you add/push_back() additional elements, invalidating all pointers:

Iterator [read: Pointer] Invalidation

(for operations) push_back, emplace_back ... If the vector changed capacity, all of them [i.e. all iterators are invalidated]. If not, only end().

"How can I fix this?"

The above invalidation rule does not apply if a vector's capacity does not change due to an insertion - since vectors do not reallocate storage unnecessarily. So if you pre-set your vector's capacity to 2 in your example (say, with v.reserve(2)), the pointer will remain valid. If you don't know the size in advance, but you can delay the construction of the second vector (with the pointers), you don't have to reserve, you'll just have the size after inserting the last element.

The approaches above are highly unrecommended, however. If you were to make your vector constant - at least in the scope of a function in which you would construct and use the second vector - you would have a strong guarantee of non-reallocation. Alternatively, if you could determine the size in advance you might use an std::array, and it would be more fitting to use pointers into that container's storage:

Iterator Invalidation

As a rule, iterators to an array are never invalidated throughout the lifetime of the array.

You might also consider storing indices into your vector (although there, as well, the vector might shrink, invalidating the indices, or you might insert elements in the middle etc).

Anyway, I suspect that you might not actually want to do any of this, i.e. it seems to be a not-so-good solution to a problem which could be handled with a different approach altogether.

PS - If the vector has a custom allocator then everything I've written might be irrelevant.

这篇关于C ++:指针向量在push_back()之后丢失引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆