今天就談一談emplace_back造成的引用失效。
直接撸代碼了:
#include
#include
#include
using namespace std;
int main()
{
vector 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
#include
#include
using namespace std;
int main()
{
vector 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
#include
#include
using namespace std;
int main()
{
vector 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
#include
#include
using namespace std;
int main()
{
vector 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
#include
#include
using namespace std;
int main()
{
vector 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就不失效呢?