执行调整大小时的向量将尝试使用移动语义将对象从旧数组移动到新数组。但是如果向量中的模板化对象不支持无抛noexcept
移动构造函数,那么它将恢复为使用复制构造,以便保留strong exception guarantee
。
但是当我尝试这个时:
#include <vector>
class X
{
public:
// Needs default constructor
X() {}
// Copy operations disabled.
X(X const&) = delete;
X& operator=(X const&) = delete;
X(X&&) // throwable move constructor
{}
X& operator=(X&&) // throwable move assignment.
{return *this;}
};
int main()
{
// Vector of Size zero
std::vector<X> data;
// Vector of Size ten.
// Since the move constructor can potentially throw
// We have to copy elements when we do a resize
//
// But X has a disabled copy semantics
// Thus I would expect a compile time error here.
data.resize(10);
}
编译时没有错误或警告:
> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
> g++ -std=c++11 test.cpp
>
答案 0 :(得分:11)
对于具有投掷移动构造函数的不可复制元素,不提供强大的异常安全保证。
[vector.capacity] / p12-14(强调我的):
void resize(size_type sz);
12 效果:如果
sz <= size()
,相当于调用pop_back()
size() - sz
次。如果size() < sz
,请附加sz - size()
默认插入的元素到序列。13 需要:
T
应为MoveInsertable
和DefaultInsertable
进入*this
。14 备注:如果异常被抛出而非移动 非
CopyInsertable
T
的构造函数没有效果。
请注意,这不需要T
CopyInsertable
。
在内部,实现可能使用std::move_if_noexcept
,尽管有名称,但实际上“如果没有超出或不可复制则移动”。