为什么允许这一举动?

时间:2015-01-30 01:45:17

标签: c++ c++11 move

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

1 个答案:

答案 0 :(得分:11)

对于具有投掷移动构造函数的不可复制元素,不提供强大的异常安全保证。

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

void resize(size_type sz); 
     

12 效果:如果sz <= size(),相当于调用pop_back()   size() - sz次。如果size() < sz,请附加sz - size()   默认插入的元素到序列。

     

13 需要T应为MoveInsertableDefaultInsertable   进入*this

     

14 备注:如果异常被抛出而非移动   非CopyInsertable T 的构造函数没有效果。

请注意,这不需要T CopyInsertable

在内部,实现可能使用std::move_if_noexcept,尽管有名称,但实际上“如果没有超出或不可复制则移动”。