C++ error C2440: 'initializing': cannot convert from 'class name' to 'same class name'
Clash Royale CLAN TAG#URR8PPP
C++ error C2440: 'initializing': cannot convert from 'class name' to 'same class name'
typedef unsigned int uint32_t;
struct Point
uint32_t x, y;
Point() :x(0), y(0)
Point(Point& p)
x = p.x;
y = p.y;
Point operator=(Point& p)
x = p.x;
y = p.y;
return *this;
;
struct Snake
Point pp;
Point p() return pp;
;
int main()
Snake s;
Point p1;
Point p2 = p1; //ok
Point p3 = s.pp; //ok
Point wtf = s.p(); //error C2440??
I tried to compile the code above and get this weird error:
error C2440: 'initializing': cannot convert from 'Point' to 'Point'
note: Cannot copy construct struct 'Point' due to ambiguous copy constructors or no available copy constructor
I figured out 2 ways to make it works: changing
Point p() return pp;
into
Point& p() return pp;
or adding a move constructor to "Point":
Point(Point&& p)
x = p.x;
y = p.y;
I decided to go with the second option. But I discover an even weirder problem:
I added some "debug code":
#include <iostream>
using std::cout;
typedef unsigned int uint32_t;
struct Point
uint32_t x, y;
Point() :x(0), y(0)
cout << "tPoint()n";
Point(Point& p)
x = p.x;
y = p.y;
cout << "tPoint(point& p)n";
Point& operator=(Point& p)
x = p.x;
y = p.y;
cout << "tPoint& operator=(Point& p)n";
return *this;
Point(Point&& p)
x = p.x;
y = p.y;
cout << "tPoint(Point&& p)n";
;
struct Snake
Point pp;
Point p() return pp;
;
int main()
cout << "Code 0:n";
Snake s;
cout << "Code 1:n";
Point p1;
cout << "Code 2:n";
Point p2 = p1; //ok
cout << "Code 3:n";
Point p3 = s.pp; //ok
cout << "Code 4:n";
Point wtf = s.p(); //error C2440??
char c;
std::cin >> c;
Which gives me:
Code 0:
Point()
Code 1:
Point()
Code 2:
Point(point& p)
Code 3:
Point(point& p)
Code 4:
Point(point& p)
Which means the move constructor was not called at all.
Why does my first code not work? And why is move constructor not called even though it's the one fixing the problem?
(I use visual studio 2017)
2 Answers
2
A copy constructor and a copy assignment operator take their input parameter by const reference, but yours are both missing the const
.
const
Also, assignment operators return *this
by reference, but yours is returning by value.
*this
Try this:
struct Point
uint32_t x, y;
Point() : x(0), y(0)
Point(const Point& p) : x(p.x), y(p.y)
Point& operator=(const Point& p)
x = p.x;
y = p.y;
return *this;
;
Note, however, that your struct is trivial, so you should let the compiler generate a default copy constructor and default copy assignment operator for you. Its implementations will suffice for your example:
struct Point
uint32_t x = 0;
uint32_t y = 0;
;
Lastly, there is no need to manually define your own uint32_t
type. C++11 has a standard uint32_t
type defined in the <cstdint>
header.
uint32_t
uint32_t
<cstdint>
I didn't think a copy constructor required a
const
Never tried that though as it restricts allowed arguments to lvalues and never had a reason to alter the argument.– doug
Aug 12 at 2:54
const
Upon reviewing the rules for copy construction, leaving out
const
is allowed but, of course, it inhibits assignment of rvalues hence the error.– doug
Aug 12 at 3:02
const
Your move constructor is not used because of copy elision, that is happening when you return from s.p()
And the reason you still need move constructor because before c++17
copy elision is optional so you have to have move constructor in case compiler decides not to use copy elision. And VS2017 is c++14
at the moment I think.
s.p()
c++17
c++14
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You may want to update your compiler as there is no error here.
– xskxzr
Aug 12 at 3:07