如題,
在VS中,當你在end之前插入時,vector擴展空間使用的是 移動建構式;
而當在end插入時,vector擴展空間使用的是 copy建構式;
本身我有一個類只允許移動構造或復制,不允許copy構造或復制........然后使用vector容器的時候,就當掉了

void F() {
struct A {
int v;
A() { printf(CODEPOS_ "A()\n"); }
~A() { printf(CODEPOS_ "\n"); }
A(const A&) { printf(CODEPOS_ "A(const A&)\n"); };
A(A&&r) { printf(CODEPOS_ "A(A&&r)\n"); r.v = 0; };
A& operator=(A&&r) { printf(CODEPOS_ "A& operator=(A&&r)\n"); r.v = 0; return *this; };
A& operator=(const A&) { printf(CODEPOS_ "A& operator=(const A&)\n");; return *this; };
};
std::vector<A> a(1);
A b;
// vector 插入其它位置與插入end,擴展空間的方法不一樣
// 插入其它位置: 呼叫_Uninitialized_move, 呼叫移動建構式
// 插入end: 呼叫_Uninitialized_copy, 呼叫copy建構式
/*
vs <vector>相關原始碼:
template<class... _Valty>
pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val)
{ // reallocate and insert by perfectly forwarding _Val at _Whereptr
...
if (_Whereptr == this->_Mylast()) // 插入end: 呼叫_Uninitialized_copy, 呼叫copy建構式
{ // at back, provide strong guarantee
_Umove_if_noexcept(this->_Myfirst(), this->_Mylast(), _Newvec);
}
else // 插入其它位置: 呼叫_Uninitialized_move, 呼叫移動建構式
{ // provide basic guarantee
_Umove(this->_Myfirst(), _Whereptr, _Newvec);
_Constructed_first = _Newvec;
_Umove(_Whereptr, this->_Mylast(), _Newvec + _Whereoff + 1);
}
...
}
*/
a.insert(a.begin(), std::move(b)); // 呼叫移動建構式 擴展空間
a.insert(a.end(), std::move(b)); // 呼叫copy建構式 擴展空間
}
uj5u.com熱心網友回復:
移動建構式通常期望不拋例外,你這個要拋例外的移動建構式標準庫的容器都不會用的。你得加上例外說明:noexcept ,保證不拋例外~~
A(A&&r) noexcept { printf(CODEPOS_ "A(A&&r)\n"); r.v = 0; };
uj5u.com熱心網友回復:
我在GCC4.8.5上試了下,跟插入位置沒關系,列印完全一樣的而且樓說的也對,不加noexcept 標準庫是不會呼叫的,加了才會呼叫
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/276342.html
標籤:C++ 語言
