C++ 为什么std::vector虽然声明为noexcept(false),但仍使用移动构造函数

C++ 为什么std::vector虽然声明为noexcept(false),但仍使用移动构造函数,c++,c++11,vector,move-semantics,noexcept,C++,C++11,Vector,Move Semantics,Noexcept,无论我在互联网上读到什么,人们都强烈建议,如果我想让我的类与std::vector(即std::vector使用我的类中的移动语义),我应该将move构造函数定义为“noexcept”(或noexcept(true)) 为什么std::vector使用它,即使我将它标记为noexcept(false)作为实验? 为什么?? 我做错了什么 在gcc 4.8.2上编译,CXX_标志设置为: --std=c++11 -O0 -fno-elide-constructors 你没做错什么 您只是错误地认

无论我在互联网上读到什么,人们都强烈建议,如果我想让我的类与
std::vector
(即
std::vector
使用我的类中的移动语义),我应该将move构造函数定义为“noexcept”(或
noexcept(true)

为什么
std::vector
使用它,即使我将它标记为
noexcept(false)
作为实验? 为什么?? 我做错了什么

在gcc 4.8.2上编译,CXX_标志设置为:

--std=c++11 -O0 -fno-elide-constructors
你没做错什么

您只是错误地认为
push_back
必须避免抛出动作:至少对于构造新元素来说,它没有

只有在重新分配向量时,才能避免抛出移动因子/移动赋值,以避免移动一半的元素,而将其余元素移动到其原始位置

该功能具有强大的异常安全保障:


要么操作成功,要么失败,什么都没有改变。

如果需要重新分配其存储空间,则首先分配新内存,然后将新元素移动到最后一个位置。如果抛出新内存被释放,并且没有任何更改,那么即使move构造函数可以抛出,您也可以得到强大的异常安全保证

如果不抛出,现有元素将从原始存储转移到新存储,这就是move构造函数的
noexcept
规范的关键所在。如果moving可能抛出并且类型是CopyConstructible,那么现有元素将被复制而不是移动

但在测试中,您只看到新元素是如何插入到向量中的,在该步骤中使用抛出构造函数总是可以的

T()
T(T&&)
~T()
~T()
--std=c++11 -O0 -fno-elide-constructors