为什么允许此举?

Why is this move allowed?

向量在调整大小时将尝试使用移动语义将对象从旧数组移动到新数组。但是,如果向量中的模板化对象不支持不抛出 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
>

没有为具有抛出移动构造函数的不可复制元素提供强异常安全保证。

[vector.capacity]/p12-14(强调我的):

void resize(size_type sz); 

12 Effects: If sz <= size(), equivalent to calling pop_back() size() - sz times. If size() < sz, appends sz - size() default-inserted elements to the sequence.

13 Requires: T shall be MoveInsertable and DefaultInsertable into *this.

14 Remarks: If an exception is thrown other than by the move constructor of a non-CopyInsertable T there are no effects.

请注意,这并不要求 TCopyInsertable

在内部,实现可能使用 std::move_if_noexcept,尽管名称如此,但实际上是 "move if noexcept or if noncopyable".