【问题标题】:getting pointers to vector elements [duplicate]获取指向向量元素的指针[重复]
【发布时间】:2017-05-25 22:22:38
【问题描述】:

我遇到了一个我不太明白的问题:

我正在用

创建一个对象 Edge
edge_vec1.push_back(Edge(src,dest));

然后我想在一个单独的向量中保留一个指向这个 Edge 的指针:

edge_vec2.push_back(&edge_vec1.back());

但是,一旦我添加了第二个 Edge 对象,指向 edge_vec2 中第一个 Edge 的指针就会失效(获取一些随机数据)。是否因为 edge_vec2 中的指针实际上指向 edge_vec1 中的某个位置,而不是底层元素?我可以通过在堆上创建我的 Edge 对象来避免这种情况,但我想了解发生了什么。

谢谢。

【问题讨论】:

  • 为什么要首先存储指向数组元素的指针?你不能只存储一个索引吗?
  • @InternetAussie 好吧,我确实将元素存储在第一个向量中。但是假设第一个容器实际上是更复杂的东西,例如邻接表。然后没有索引,但我想保留一个快速迭代所有边缘的选项
  • 最简单的解决方案是在两个容器中都存储指针并动态创建对象。
  • 这个问题和答案非常依赖于容器。对于不同的容器,失效发生的方式非常不同;例如,使 std::list 中的迭代器无效就更难了。如果第一个容器不是字面上的vector,那么这不是您可以为这个问题简化的细节。
  • @Logman 是的,直到您必须管理所有动态分配的内存。智能指针在这方面会有所帮助。

标签: c++ pointers vector


【解决方案1】:

当一个新元素被添加到一个向量中时,向量可以被重新分配。所以之前指向向量元素的指针值可能是无效的。

您首先应该为防止重新分配的向量保留足够的内存。

edge_vec2.reserve( SomeMaxValue );

【讨论】:

  • 谢谢,我怀疑这是怎么回事。我猜,如果可用的值只是一个向量元素,它就不能有一个永久的指针。
  • 如果你可以增长向量,不。
  • @DanielH 我认为代表边的元素数量对于给定的图形是固定的。
【解决方案2】:

来自http://en.cppreference.com/w/cpp/container/vector/push_back

如果新的 size() 大于 capacity() 则所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。

在向vector 添加项目时,依赖对对象的指针/引用是个坏主意。最好将索引的值存储起来,然后使用索引从vector中获取项目。

edge_vec2.push_back(edge_vec1.size()-1);

稍后,您可以使用:

edge_vec1[edge_vec2[i]]

对于i 的一些有效值。

【讨论】:

  • 索引不是我的选择(参见 cmets),但感谢您确认我的指针已失效。
【解决方案3】:

std::vector 的要求是底​​层存储是一个连续的内存块。因此,当您想要插入一个元素但当前分配的块不足以容纳附加元素时,向量必须重新分配其所有元素。发生这种情况时,所有迭代器和指针都将失效,因为整个块被重新分配(移动)到完全不同的内存部分。

成员函数容量可用于查询在不重新分配底层内存块的情况下可以插入的最大元素数量。查询此示例代码:

std::vector<int> vec;
for(int i = 0; i < 1000; i++) {
     bool still_has_space = vec.capacity() > vec.size();
     if (!still_has_space) std::cout << "Reallocating block\n"; 
     vec.push_back(i);
}

如果不需要连续内存布局的强有力保证,你可能会更好地使用 std::deque 而不是 std::vector。它允许在任一端推动元素,而无需在任何其他元素周围移动。您可以用它换取稍差的迭代速度。

 std::deque<int> deq;
 std::vector<int*> pointers;
 for(int i = 0; i < 1000; i++) {
      deq.push_back(i);
      pointers.push_back(&deq.back());
 }
 for(auto p : pointers) std::cout << *p << "\n"; // Valid

【讨论】:

    猜你喜欢
    • 2011-03-12
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多