繁体   English   中英

push_backs到std :: vector <std::reference_wrapper<type> &gt;

[英]push_backs to a std::vector<std::reference_wrapper<type>>

考虑在push_back s到std::reference_wrapperstd::vector的尝试:

#include <iostream>
#include <vector>
#include <functional>
int main()
{
  std::vector<int> v_i;
  std::vector<std::reference_wrapper<int>> s_i;
  for(int i=0;i<10;++i)
  {
    v_i.push_back(i);
    s_i.push_back(std::ref(v_i[i]));
  }
  std::cout<<v_i[0]<<std::endl;
  std::cout<<s_i[0].get()<<std::endl;
  return -1;
}

我期望[]运算符返回对v i-th元素的引用,并且从此处给出的可能实现中,我们可以合理地假设附加到s_istd::reference_wrapper对象持有该指针的副本,指向v_i[i]的正确地址。 但是,上面代码的输出是

0
1980603512 //or some other random garbage value

显然,在循环内部构造的std::reference_wrapper指向临时对象。 为什么会发生这种情况?追加到s_i的正确方法是什么?

顺便说一句,我正在使用g++ 5.4.0 (带有-std=c++0x标志)。

我们可以合理地假设附加到s_i的std :: reference_wrapper对象持有指向v_i [i]正确地址的指针的副本。

不,您不能合理地假设这一点。 这是因为

v_i.push_back(i);

可以导致v_i重新分配; 实际上,您几乎可以保证在某些时候会在这里发生这种情况。 任何重新分配都会立即自动使所有现有的迭代器和指向向量的现有内容的指针无效。

如果您将任何普通指针保存到std::vector中的某些元素,然后尝试push_back() ,则导致这些指针的重新分配和无效,这没有什么不同。 这些指针的任何后续取消引用都会导致未定义的行为。

所示代码在这里所做的基本上是等效的,只是使用了一个额外的std::ref洋葱层来包装整个东西,但是在逻辑上等效了未定义的行为。

如果您希望在此处避免未定义的行为,那么唯一可行的方法是充分reserve()向量,以确保后续的push_back ()不会发生重新分配。

问题是push_back操作可能会使std::vector元素的迭代器\\ references \\ pointers无效。

push_back

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

随着您的std::vector的增长,有时会出现一个新大小大于当前容量的时刻。 如上所述,它导致对std::vector元素的reference \\ pointers无效。

在这种情况下, std::reference_wrapper无效。

进一步使用无效的std::reference_wrapper会导致UB

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM