C++ C++;错误C2440:&x27;初始化';:无法从';类名';至';相同的类名';

C++ C++;错误C2440:&x27;初始化';:无法从';类名';至';相同的类名';,c++,C++,我试着编译上面的代码,得到了一个奇怪的错误: 错误C2440:“正在初始化”:无法从“点”转换为“点” 注意:由于复制构造函数不明确或没有可用的复制构造函数,无法复制构造结构“点” 我想出了两种方法让它起作用:改变 typedef unsigned int uint32_t; struct Point { uint32_t x, y; Point() :x(0), y(0) {} Point(Point& p) { x = p.x;

我试着编译上面的代码,得到了一个奇怪的错误:

错误C2440:“正在初始化”:无法从“点”转换为“点”

注意:由于复制构造函数不明确或没有可用的复制构造函数,无法复制构造结构“点”

我想出了两种方法让它起作用:改变

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??
}
进入

或将移动构造函数添加到“点”:

我决定采用第二种选择。但我发现了一个更奇怪的问题:

我添加了一些“调试代码”:

这意味着根本没有调用move构造函数

为什么我的第一个代码不起作用?为什么不调用move构造函数,即使它是解决问题的构造函数


(我使用visual studio 2017)

一个复制构造函数和一个复制赋值操作符通过const引用获取其输入参数,但您的两个操作符都缺少
const

此外,赋值运算符通过引用返回
*此
,但您的运算符通过值返回

试试这个:

Code 0:
    Point()
Code 1:
    Point()
Code 2:
    Point(point& p)
Code 3:
    Point(point& p)
Code 4:
    Point(point& p)
但是,请注意,您的结构非常简单,因此您应该让编译器为您生成一个默认的复制构造函数和默认的复制赋值运算符。其实现足以满足您的示例:

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;
    }
};

最后,无需手动定义自己的
uint32\t
类型。C++11在
标题中定义了一个标准的
uint32\t
类型

您的移动构造函数没有被使用,因为复制省略,当您从
s.p()
返回时会发生这种情况,并且您仍然需要移动构造函数的原因是,在
c++17
之前,复制省略是可选的,所以您必须有移动构造函数,以防编译器决定不使用复制省略。我认为VS2017目前是
c++14

我不认为复制构造函数需要
const
但从未尝试过,因为它将允许的参数限制为左值,并且从来没有理由更改参数。在查看复制构造规则时,可以省略
const
,但是,当然,它会禁止分配右值,因此会出现错误。由于没有错误,您可能需要更新编译器。
Point(Point&& p) {
    x = p.x;
    y = p.y;
}
#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;
}
Code 0:
    Point()
Code 1:
    Point()
Code 2:
    Point(point& p)
Code 3:
    Point(point& p)
Code 4:
    Point(point& p)
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;
    }
};
struct Point {
    uint32_t x = 0;
    uint32_t y = 0;
};