编译器声明的隐式移动构造函数

时间:2015-11-20 22:28:24

标签: c++11

根据C ++ 11 [12.8.9],这个(非平凡的)类X没有隐式声明的移动构造函数,因为X有一个用户声明的复制ctor,一个用户声明的复制赋值操作符,一个用户-declared dtor:

// This counter for objects of class X is only there to make X 'nontrivial':
static int xc = 0;

class X {
public:
        X() : p(42) { ++xc; /* ...more nontrivial stuff... */; }
        explicit X(const int &t) noexcept : p(t) { ++xc; /* ... */ }
        X(const X & other) noexcept : p(other.p) { ++xc; /* ... */ }
        //X(X &&) = delete;  /* **this is the line in question** */
        X& operator=(const X & other) { p = other.p; /* ... */ return *this; }
        X& operator=(X && other) { p = other.p; /* ... */ return *this; }
        ~X() { --xc; /* ... */ }
private:
        int p;
};

但是,如果我取消注释删除的移动ctor(即如果我删除移动ctor),我的编译器(GCC 5.2)突然抱怨在编译时移动ctor被删除:

X f(int x)
{
        return X(x);
}

我本以为没有删除移动ctor,编译器在从函数f返回X时使用copy ctor,因为这里不允许隐式移动ctor。但那么:为什么明确删除移动ctor会有所作为呢?

1 个答案:

答案 0 :(得分:2)

条款"未定义"和"删除"移动构造函数是不同的。即使删除了重载分辨率,也会选择明确定义的移动构造函数。

如果要禁止对象移动并防止重载决策选择已删除的移动构造函数,则应隐式删除移动构造函数:

  

(自C ++ 14开始)删除的隐式声明的移动构造函数是   被重载决议忽略(否则会阻止   从右值开始复制初始化)

例如,您可以使用已删除的移动构造函数从基类继承该类。