##实战c++中的vector系列--emplace_back造成的引用失效
上篇将了对于struct或是class为何emplace_back要优越于push_back,但是还有一些细节没有提及。今天就谈一谈emplace_back造成的引用失效。
直接撸代码了:
~~~
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<int> ivec;
ivec.emplace_back(1);
ivec.emplace_back(ivec.back());
for (auto it = ivec.begin(); it != ivec.end(); ++it)
cout << *it << " ";
return 0;
}
//输出:
1 -572662307
~~~
尝试1:不直接给emplace_back传递ivec.back():
~~~
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<int> ivec;
ivec.emplace_back(1);
auto &it = ivec.back();
ivec.emplace_back(it);
for (auto it = ivec.begin(); it != ivec.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
1 -572662307
~~~
尝试2:不给emplace_back传递引用:
~~~
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<int> ivec;
ivec.emplace_back(1);
auto it = ivec.back();
ivec.emplace_back(it);
for (auto it = ivec.begin(); it != ivec.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
1 1
~~~
我们如愿以偿,这时候应该可以得到结论了,ivec.back()返回的是引用,但是这个引用失效了,所以才会输出不正确;我们之前也提到过,重新分配内存会造成迭代器的失效,这里是造成了引用的失效。
再回头看看emplace_back的描述:
if a reallocation happens, all iterators, pointers and references related to this container are invalidated.
Otherwise, only the end iterator is invalidated, and all other iterators, pointers and references to elements are guaranteed to keep referring to the same elements they were referring to before the call.
进一步。
尝试3:避免emplace_back引起重新分配内存:
~~~
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<int> ivec;
ivec.reserve(4);
ivec.emplace_back(1);
ivec.emplace_back(ivec.back());
for (auto it = ivec.begin(); it != ivec.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
1 1
~~~
但是这个时候问题来了,如果不使用emplace_back而改用push_back呢?
~~~
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main()
{
vector<int> ivec;
ivec.push_back(1);
ivec.push_back(ivec.back());
ivec.push_back(ivec.back());
ivec.push_back(ivec.back());
for (auto it = ivec.begin(); it != ivec.end(); ++it)
cout << *it << " ";
return 0;
}
//输出:
1 1 1 1
~~~
为什么使用push_back就不失效呢?
- 前言
- 构造、operator=和assign区别
- 将迭代器转换为索引
- copy set to vector(别混淆了reserve和resize)
- 使用vector构造二维数组
- 可怕的迭代器失效(vector重新申请内存)
- 可怕的迭代器失效之二(删除vector中元素)
- vector<unique_ptr<>>初始化(所有权转移)
- vector<unique_ptr<>>作为函数的参数
- vector<unique_ptr<>>赋值给vector<unique_ptr<>>
- creating vector of local structure、vector of structs initialization
- 知道emplace_back为何优于push_back吗?
- emplace_back造成的引用失效
- vector的一些异常
- vector的遍历(stl算法、vector迭代器(不要在循环中判断不等于end())、operator[])
- 使用sort算法对vector进行排序(对vector<string>排序、使用稳定的排序std::stable_sort())
- vector应用之STL的find、find_if、find_end、find_first_of、find_if_not(C++11)
- 使用sort算法对vector<unique_ptr<string>>进行排序(sort函数“应输入 2 个参数,却提供了 3 个)
- 对vector<自定义类>使用std::find 和 std::find_if 算法