1

考虑以下代码,它在 Clang、GCC 和 VS 2015 下编译(在线示例):

#include <utility>

class S 
{
public:
    S(int x) : i(x) { }
    ~S() { }

    S(S&&)  = default;

    S(const S& )            = delete;
    S& operator=(S&&)       = delete;
    S& operator=(const S&)  = delete;

private:
    int i;
};

S GetS() 
{ 
    // This is a contrived example with details elided. Assume 
    // there's a reason in the actual use case for returning via 
    // std::move.
    return std::move( S(999) ); 
}

int main()
{
    S tmp = GetS(); // <-- Assignment allowed even though assignment operator is deleted?

    return 1;
}

我不清楚为什么这条线

S tmp = GetS(); 

编译,执行移动构造函数而不是移动赋值运算符。

我知道 RVO 允许省略构造和赋值作为优化,但我的理解是,如果在代码中显式使用该运算符,则显式删除运算符会导致编译失败。

C++11 规范中是否有某些条款允许编译器将赋值初始化转换为复制构造,即使已显式删除类型的赋值运算符?

4

1 回答 1

3

那是因为这不是分配:

S tmp = GetS(); 

它称为复制初始化并调用您已明确默认的移动构造函数。

基本上,赋值运算符只在已经存在的对象上调用。tmp尚不存在,此语句将其初始化。因此,您正在调用构造函数。

请注意,内部发生的事情GetS()不会影响如何tmp构造的规则。GetS()无论哪种方式都是右值。

于 2016-03-29T18:00:03.603 回答