【问题标题】:Vectors and Pointers向量和指针
【发布时间】:2017-01-09 21:38:16
【问题描述】:

向量和指向其元素的指针的主要问题是,只要调用push_back,它们就可以在内存中重新分配,从而导致指针无效。

我正在尝试实现一个后缀特里树,我将一个数据结构node 存储在一个节点向量中。我知道对于大小为 n 的字符串,数字 n(n+1)/2 是树中节点数的上限。

代码也是如此

std::string T = "Hello StackOverflow!";
std::vector<Node> nodes;

int n = T.length();
nodes.reserve(n*(n+1)/2);

保证我创建的任何引用nodes 元素的指针都不会失效?也就是说,这会保证向量不会被重新分配吗?


编辑:我已经实现了这一点,并且在运行时不断收到以下错误。

terminate called after throwing an instance of 'std::out_of_range'
what():  basic_string::at: __n (which is 0) >= this->size() (which is 0)
Aborted (core dumped)

有什么可能导致这种情况的想法吗?

【问题讨论】:

  • 查看std::dequepush_back 不会使引用/指针无效(但迭代器无效)。 en.cppreference.com/w/cpp/container/deque
  • @Kevin:问题是关于std:::vector,而不是std::deque :)。
  • @AlexD 我知道,如果他想要一个支持push_back 并且不会使引用无效的容器,我只是提到了一个替代方案。 std::deque 有其用途,但经常被忽略。不过,下面的答案可能适合这个问题。

标签: c++ pointers vector


【解决方案1】:

根据标准(N4140):

23.3.6.3 向量容量
....

void reserve(size_type n);

....
reserve() 之后,capacity() 大于等于reserve 的参数如果 发生重新分配;否则等于capacity() 的先前值。发生重新分配 此时当且仅当当前容量小于reserve()的参数。

23.3.6.5 矢量修饰符
....

void push_back(const T& x);
void push_back(T&& x);

备注: 如果新容量大于旧容量,则会导致重新分配。如果没有发生重新分配, 插入点之前的所有迭代器和引用都保持有效。

【讨论】:

  • 但是resereve() 会修复给定大小的向量容量吗?
  • @LukeCollins 这正是reserve 函数的作用
  • 标准:reserve()之后,如果发生重新分配,则capacity()大于或等于reserve的参数;否则等于 capacity() 的前一个值。
  • @M.M 谢谢 - 我不确定它是否有任何条件。因此,鉴于我确定我的向量超过 n(n+1)/2,我应该没问题?
【解决方案2】:

如果你小心的话,你可以确定你的指针不会失效。见std::vector::push_back。它说的是关于失效:

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

只需确保您没有push_back 超出容量或调用其他可能无效的方法。无效的方法列表在“迭代器无效”部分中提供here

【讨论】:

  • 但是resereve() 会修复给定大小的向量容量吗?
  • @LukeCollins std::vector::reserve 不会将容量设置为精确值,但它确实保证新容量将至少与提供给@987654327 的值一样大 @.
  • 感谢您的回复。你能帮我完成上面的编辑吗?
  • @LukeCollins 这是一个不相关的问题。从错误消息中,您可以访问不包含任何字符的字符串的第一个字符。
  • #Francois,你能帮我解决这个问题吗? stackoverflow.com/questions/41558092/…
猜你喜欢
  • 2011-08-04
  • 2020-10-23
  • 2013-01-04
  • 2013-11-21
  • 1970-01-01
  • 2020-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多