为什么在向量重新分配期间没有调用 noexcept 移动构造函数?

Why noexcept move constructor is not getting called during vector reallocation?

正如我们所知,当新元素添加到 std::vector(通过 push_back)时,它可能缺少 space,对于这些情况,vector 会分配更大的内存块保留它的所有元素,然后从现有块转移到新的 one.In C++98,这是通过从旧位置复制元素然后销毁这些对象来完成的,因此它可以提供强大的异常保证,在 C++ 中11 它可以使用移动构造函数进行优化,前提是它是 noexcept 但是如果我的析构函数是 noexcept(false) 会发生什么那么为什么优化没有发生?

#include <iostream>
#include <vector>

class X
{
public:
    X()
    {
    }
    X(const X& ob) noexcept
    {
      std::cout<<"Copy Constructor...."<<std::endl;
    }
    X(X&& ob) noexcept
    {
       std::cout<<"Move Constructor...."<<std::endl;
    }
    ~X() noexcept(false)
    {
    }
};
int main()
{
   std::vector<X> myobs;
   for(int i=0;i<1000;i++)
   {
      myobs.push_back(X());
   }
   return 0;
}

为什么在上面的场景中调用了复制构造函数,还要注意,如果我将析构函数设置为 noexcept(默认行为),那么只会调用移动构造函数。

添加我对强异常保证(在 vector::push_back 中)的理解是 none 旧内存中的元素被销毁,直到所有元素都被成功复制,这意味着最后调用析构函数所以不管他们是不是 noexcept 与否

问题出在 is_nothrow_move_constructible<T> 的规范上,目前指定的规范是检查表达式

T(declval<T&&>())

是 noexcept,但这涉及(临时的)析构函数以及移动构造函数。这可以说是库缺陷,是正在进行的 LWG 2116 的主题。 GCC遵循规范是正确的;是规范本身不好。