This snippet is compiled without errors in Visual Studio 2013 (Version 12.0.31101.00 Update 4)
class A
{
public:
A(){}
A(A &&){}
};
int main(int, char*)
{
A a;
new A(a);
return 0;
}
while it is compiled with this error in Visual Studio 2015 RC (Version 14.0.22823.1 D14REL):
1>------ Build started: Project: foo, Configuration: Debug Win32 ------
1> foo.cpp
1>c:\dev\foo\foo.cpp(11): error C2280: 'A::A(const A &)': attempting to reference a deleted function
1> c:\dev\foo\foo.cpp(6): note: compiler has generated 'A::A' here
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I think that the compiler shipped with Visual Studio 2015 generates the Copy Constructor and marks it as =delete
and so I get the error C2280 (which, by the way, I cannot find documented on msdn.microsoft.com).
Now, let's say I have a codebase which is compilable with Visual Studio 2013 (and it works because it relies on the code generated automatically by the compiler) but not compilable with Visual Studio 2015 due to C2280, how can I fix the problem?
I was thinking to declare class A
in this way:
class A
{
public:
A(){}
A(A &&){}
A(const A&)=default;
};
am I missing something?
I had the same problem and it was due to a poorly defined member variable:
Putting this in will cause the copy constructor to be deleted. Get rid of the "const" and assign in the constructor.
From [class.copy]/7, emphasis mine:
There is an equivalent section with similar wording for copy assignment in paragraph 18. So your class is really:
which is why you can't copy-construct it. If you provide a move constructor/assignment, and you still want the class to be copyable, you will have to explicitly provide those special member functions:
You will also need to declare a move assignment operator. If you really have a need for these special functions, you will also probably need the destructor. See Rule of Five.
If you write a user-defined move constructor for your class, the copy constructor will be deleted. This is because if a class needs special behaviour for its move constructor, it probably needs some similar behaviour in its copy constructor, so the copy constructor will be deleted to stop you from inadvertently using the default behaviour.
If you want to define your own move constructor and use the default copy constructor, you need to declare it as
default
, like you suggested in your question:Note that if you define a custom move constructor, you should think about your assignment operators and destructor as well.