简体   繁体   English

C ++错误C2440:“正在初始化”:无法从“类名”转换为“相同的类名”

[英]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' 错误C2440:“正在初始化”:无法从“点”转换为“点”

note: Cannot copy construct struct 'Point' due to ambiguous copy constructors or no available copy constructor 注意:由于复制构造函数模棱两可或没有可用的复制构造函数,因此无法复制构造struct'Point'

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(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. 这意味着根本没有调用move构造函数。

Why does my first code not work? 为什么我的第一个代码不起作用? And why is move constructor not called even though it's the one fixing the problem? 并且为什么即使它是解决问题的一个方法,也未调用move构造函数?

(I use visual studio 2017) (我使用Visual Studio 2017)

A copy constructor and a copy assignment operator take their input parameter by const reference, but yours are both missing the const . 复制构造函数和复制赋值运算符通过const引用获取输入参数,但是您都缺少const

Also, assignment operators return *this by reference , but yours is returning by value . 同样,赋值运算符通过引用返回*this ,但是您的返回value

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. 最后,无需手动定义自己的uint32_t类型。 C++11 has a standard uint32_t type defined in the <cstdint> header. C ++ 11在<cstdint>标头中定义了标准的uint32_t类型。

Your move constructor is not used because of copy elision, that is happening when you return from sp() 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. 您的move构造函数未使用是因为复制省略,当您从sp()返回时会发生这种情况,并且仍需要move构造函数的原因是因为在c++17之前,copy elision是可选的,因此您必须拥有move构造函数以防编译器决定不要使用复制省略。 And VS2017 is c++14 at the moment I think. 我认为目前VS2017是c++14

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++嵌套类模板错误C2440&#39;=&#39;:无法从&#39;type&#39;转换为&#39;same type&#39; - C++ Nested class template Error C2440 '=': cannot convert from 'type' to 'same type' 错误C2440:“正在初始化”:无法从“ LPVOID”转换为“ UINT” - error C2440: 'initializing' : cannot convert from 'LPVOID' to 'UINT 错误 C2440:“正在初始化”:无法从 - error C2440: 'initializing' : cannot convert from 错误C2440:“正在初始化”:无法从“类名*”转换为“类名” - error C2440: 'initializing' : cannot convert from 'classname *' to 'classname' 错误 C2440:“正在初始化”:无法从“CTable”转换为“CTable” - Error C2440: 'initializing': cannot convert from 'CTable' to 'CTable' C2440:“正在初始化”:无法从“A”转换<double> '到'一个<double> '</double></double> - C2440: 'initializing': cannot convert from 'A<double>' to 'A<double>' C ++类型转换:错误C2440:“正在初始化”:无法从“ HRESULT”转换为“ std :: basic_string &lt;_Elem,_Traits,_Alloc&gt;” - c++ type conversion: error C2440: 'initializing' : cannot convert from 'HRESULT' to 'std::basic_string<_Elem,_Traits,_Alloc>' 错误 3 错误 C2440:“正在初始化”:无法从“void *”转换为“Socket *” - Error 3 error C2440: 'initializing' : cannot convert from 'void *' to 'Socket *' 错误C2440:“正在初始化”:无法从“ std :: _ A_iterator &lt;_B&gt;”转换为“ std :: _ A_iterator &lt;_B&gt;” - error C2440: 'initializing' : cannot convert from 'std::_A_iterator<_B>' to 'std::_A_iterator<_B>' 错误C2440:“正在初始化”:无法从“ std :: _ Vector_iterator &lt;_Ty,_Alloc&gt;”转换为“类型*” - error C2440: 'initializing' : cannot convert from 'std::_Vector_iterator<_Ty,_Alloc>' to 'type *'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM