Reputation: 2459
Consider the following code, which compiles under Clang, GCC, and 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;
}
I'm unclear as to why the line
S tmp = GetS();
compiles, executing the move constructor instead of the move assignment operator.
I know that RVO allows construction and assignment to be elided as an optimization, but it was my understanding that explicitly deleting an operator should cause compilation to fail if that operator is explicitly used in the code.
Is there some clause in the C++11 specification that allows a compiler to transform assignment initialization into copy construction, even when assignment operators for a type have been explicitly deleted?
Upvotes: 1
Views: 192
Reputation: 302757
That's because this isn't assignment:
S tmp = GetS();
it's called copy-initialization and invokes the move constructor, which you have explicitly defaulted.
Basically, an assignment operator is only invoked on an object that already exists. tmp
doesn't exist yet, this statement initializes it. As such, you're calling a constructor.
Note that what happens inside of GetS()
does not affect the rules for how tmp
is constructed. GetS()
is an rvalue either way.
Upvotes: 3