【问题标题】:How does vector work while pushing back a reference of its element to itself?vector 在将其元素的引用推回给自身时如何工作?
【发布时间】:2016-06-26 06:51:59
【问题描述】:

我首先声明string 中的vector,称为test。然后我 push_back string HelloWorld 并让 a 成为 referencetest[0]。然后我 push_back atest。但是,我分别在 push_back 之前和之后打印了a,并观察到a 在推入test 后什么都没有。为什么a 什么都不是?向量在将其元素的reference (a) 推回自身时如何工作?这是否意味着a 不再是referencetest[0]
谢谢。

备注:如果我 push_back test[0]a 也变成了无。但是test[0] 仍然是“你好”。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
     vector<string> test;
     test.push_back("Hello");
     test.push_back("World");
     string& a = test[0];
     cout << "1"<< a << "\n";
     test.push_back(a);          //or : test.push_back(test[0]);
     cout << "2"<< a << "\n"; 
} 

Live Demo

输出:

1Hello
2

更新:

我明白了,感谢下面的答案和 cmets。我打印了 testsizecapacity 并观察到它们都是 2 。执行test.push_back(a) 时,向量test 分配新内存并将其旧元素复制到新内存。因此 a ,它的旧元素的引用,变得未定义。

这是使用 reserve 的类似代码。我认为a 变为未定义的原因与我最初的问题相同。 (如果我错了,请告诉我。)

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
     vector<string> test;
     test.push_back("Hello");
     test.push_back("World");
     string& a = test[0];
     cout << "1"<< a << "\n";
     cout << "size:" << test.size() << " capacity:" <<test.capacity() <<"\n";  
     test.reserve(3);       
     cout << "2"<< a << "\n"; 
} 

输出:

1Hello
size:2 capacity:2
2

【问题讨论】:

  • push_back 上,所有对向量元素的迭代器、指针和引用都将失效(除了您未测试的某些情况)

标签: c++


【解决方案1】:
test.push_back(a);          //or : test.push_back(test[0]);

添加a 的副本作为test 的最后一个元素。 a 是对 test 中元素的引用这一事实根本不相关。

在那次调用之后,a 可能是悬空引用。像在行中一样使用它

 cout << "2"<< a << "\n"; 

是未定义行为的原因。

另一方面,test[0] 返回对test 的第一个元素的引用。它可能是对与 a 引用的对象不同的对象的引用。

【讨论】:

  • 谢谢。但是为什么a 的副本会使a 成为悬空引用?不就是“复制”吗?为什么引用 a 变得未定义?现在我将 test.push_back(a) 替换为 string b = a 。这不是将a 复制到b 就像我原来的问题一样吗?但是在将 a 复制到 b 之后,a 不是未定义而是“你好”(test[0])。
  • std::vector::push_back 如果当前容量不足以容纳新元素,则可能需要分配内存。当它这样做时,它会在将旧对象复制/移动到新内存后删除旧内存。因此,对旧对象的引用可能会变成悬空引用。
【解决方案2】:

根据std::vector 定义,vector::push_back 使对容器的现有引用无效,string&amp; a 变得未定义。见http://en.cppreference.com/w/cpp/container/vector/push_back

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

由于您在推送a 之前不知道向量的容量是多少,因此您无法确定您的引用没有失效;这是未定义的行为,在某些情况下可能“有效”,但在其他情况下可以做任何事情。

【讨论】:

    猜你喜欢
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2021-10-09
    相关资源
    最近更新 更多