明确删除赋值运算符时允许从右值赋值?
Assignment from rvalue allowed when assignment operator explicitly deleted?
考虑以下代码,它在 Clang、GCC 和 VS 2015 (online example) 下编译:
#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 规范中是否有某些子句允许编译器将赋值初始化转换为复制构造,即使类型的赋值运算符已被显式删除?
那是因为这不是作业:
S tmp = GetS();
它被称为 copy-initialization 并调用您已明确默认的移动构造函数。
基本上,赋值运算符仅在已存在的对象上调用。 tmp
还不存在,这条语句初始化它。因此,您正在调用构造函数。
请注意,GetS()
的 内部 发生的事情不会影响 tmp
的构建规则。 GetS()
无论如何都是右值。
考虑以下代码,它在 Clang、GCC 和 VS 2015 (online example) 下编译:
#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 规范中是否有某些子句允许编译器将赋值初始化转换为复制构造,即使类型的赋值运算符已被显式删除?
那是因为这不是作业:
S tmp = GetS();
它被称为 copy-initialization 并调用您已明确默认的移动构造函数。
基本上,赋值运算符仅在已存在的对象上调用。 tmp
还不存在,这条语句初始化它。因此,您正在调用构造函数。
请注意,GetS()
的 内部 发生的事情不会影响 tmp
的构建规则。 GetS()
无论如何都是右值。