【问题标题】:store a pointers to element that inside a fixed size vector存储指向固定大小向量内的元素的指针
【发布时间】:2020-04-12 09:57:32
【问题描述】:

我无法说服自己存储指向 vector.end() 的指针是安全的 (即任何向量 end() 迭代器返回)

数据是

std::vector<unsigned char> data;
auto end = &(*data.end());
block b(end, size);
blocks.push_back(b);
data.insert(data.end(), (unsigned char*) ptr_data, (unsigned char*) ptr_data + size);

我的问题是。这个地址是否可以改变( &*(data.end() ),条件是向量容量预先分配并且客户端永远不会插入超过向量应该存储的内容。

所以它应该是内存中的一个连续区域,所以我假设vector不会做任何memove操作,因此我可以存储指向不同元素的指针。 (所以这里块存储指向任何 data.end() 指向的指针(在插入数据向量之前) 以及关于该数据向量内可变大小数据的元数据。

谢谢。

【问题讨论】:

  • auto end = &amp;(*data.end()) -- 取消引用 end 迭代器是未定义的行为。例如,此代码在 Visual Studio 下运行时会导致 assert() 触发。 See this
  • 只需存储偏移量而不是指针或迭代器,您就不必担心它
  • auto end = &amp;(*data.end());代替auto end = data.data() + data.size();
  • 这是一个问题:(我想这完全取决于向量如何预分配容量。如果内存由分配器以给定容量预分配,它不应该指向外部的东西)跨度>
  • @Kevin 你说得对,它可能是一个更好的解决方案。但我不太确定固定容量向量的失效。 Vector 有自己的内存管理,所以我不确定它保证什么。

标签: c++ iterator stdvector


【解决方案1】:

只要没有得到invalidated,存储std::vector::end()之类的迭代器应该是安全的。有很长的失效规则列表,但它的要点(与您的示例相关)是这样做是可以的,直到您点击push_back()

blocks.push_back(b);

此调用使迭代器无效,因为它调整了它的大小。您需要再次获取 blocks.end() 才能使其有效。


需要注意的一点是,您可能不应该取消对 end() 的引用。 It is unsafe。但是,您的用例与this problem with regular arrays 非常相似。这解决了常规数组,而不是向量,但我想它会非常相似。

长话短说,如果您获取数组元素的过去 1 结尾的地址,它可能会或可能被视为未定义的行为,并被某些人视为标准中的缺陷。

相反,您实际上不需要存储取消引用的迭代器的地址,只需存储迭代器即可:

auto end = data.end();

迭代器的工作原理类似于指针,因此没有真正的理由在这里获取一个的地址。

【讨论】:

  • 哦,这个链接太棒了,我正在查看 STL Vector 代码来找出这个规则 :))
  • 它不应该是安全的。取消引用 end() 迭代器是未定义的行为。
  • @PaulMcKenzie 并不是说​​取消引用没关系。更新以更清楚地表达我的意思。
  • @PaulMcKenzie 我想我现在修好了。
猜你喜欢
  • 2011-03-12
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
相关资源
最近更新 更多