64,682
社区成员
发帖
与我相关
我的任务
分享
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构造函数 扩展空间
}
...
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);
}
...
如原始注释,vector在末尾插入时(比如:push_back、emplace_back )提供强异常保证;其它位置则提供基本异常保证。
强异常保证期望被调用函数不抛出异常,而这个对象的移动构造函数可以抛出异常,所以就不会被调用了。这函数名一看就懂啊:_Umove_if_noexcept
_Umove_if_noexcept源码显示,当移动构造函数不抛异常时,调用移动构造,否则调用copy构造:
void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, true_type) {
// move [_First, _Last) to raw _Dest, using allocator
_Uninitialized_move(_First, _Last, _Dest, _Getal());
}
void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, false_type) {
// copy [_First, _Last) to raw _Dest, using allocator
_Uninitialized_copy(_First, _Last, _Dest, _Getal());
}
void _Umove_if_noexcept(pointer _First, pointer _Last, pointer _Dest) {
// move_if_noexcept [_First, _Last) to raw _Dest, using allocator
_Umove_if_noexcept1(_First, _Last, _Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<_Ty>, negation<is_copy_constructible<_Ty>>>>{});
}