为什么以这种方式初始化与复制构造函数有关?[复制]

Why initialization in this way has something to do with the copy constructor? [duplicate]

提问人:weizao 提问时间:7/28/2022 更新时间:7/28/2022 访问量:95

问:

我是学习C++的新手。我只是尝试在 vs code 中运行以下代码,但它报告了错误

#include <iostream>
using namespace std;
class Entity
{
public:
    Entity()
    {
        cout << "default" << endl;
    }
    Entity(int x)
    {
        cout << x << endl;
    }
    Entity(Entity &e)
    {
        cout << "copy" << endl;
    }
    Entity &operator=(const Entity &e)
    {
        cout << "assignment" << endl;
        return *this;
    }
};
int main(void)
{
    Entity e = Entity(8);
}

错误是cannot bind non-const lvalue reference of type 'Entity&' to an rvalue of type 'Entity' Entity e = Entity(8);

我在网上搜索了很长时间。有人说这是因为编译器创建的临时对象不能绑定到非常量引用,所以添加 const 修饰符就可以了。

Entity(const Entity &e)
{
    cout << "copy" << endl;
}

似乎我正在使用复制构造函数初始化一个对象,否则编译器不应报告错误。但事实是我正在使用参数化构造函数来做到这一点。 让我感到困惑的是,为什么以这种方式进行初始化与复制构造函数有关?

C++ 引用 初始化 常量 copy-constructor

评论

0赞 JaMiT 7/28/2022
考虑类似的情况。 基于这两行,您希望使用哪个构造函数来构造?Entity e(8);Entity f = e;f
0赞 273K 7/28/2022
仅使用参数化构造函数是 。您的实际初始化是Entity e(8);Entity e(Entity(8));
0赞 mch 7/28/2022
您使用哪种编译器? 是语法糖,并且不需要(错误的)复制构造函数。您的代码不会创建错误消息:godbolt.org/z/xzsnsaPvcEntity e = Entity(8);Entity e {8};
0赞 weizao 7/28/2022
编译器是MinGW-W64 gcc版本8.1.0
0赞 user12002570 7/28/2022
@weizao 从 dupe Why C++ copy constructor must use const object?中,“你不能从临时引用创建副本,因为临时对象是右值的,不能绑定到对非 const 的引用”。另请参阅为什么复制构造函数参数是 const?

答:

2赞 463035818_is_not_an_ai 7/28/2022 #1

Entity(8);调用构造函数 。然后你用那个临时来构造.因为它是临时的,所以不能将其传递给具有非常量引用参数的方法。Entity(int x)e

有关更多详细信息,请参阅什么是复制省略和返回值优化?。简而言之:复制构造函数必须可用,但复制将被省略。感谢@MilesBudnek的链接。

评论

0赞 weizao 7/28/2022
我明白了,非常感谢。但我还有一个问题,为什么在添加 const 修饰符后不会调用显式复制构造函数。添加 const 修饰符后,程序不输出 “copy” 字符串,只输出 8
0赞 Miles Budnek 7/28/2022
@weizao 请参阅“什么是复制省略和返回值优化?在 C++17 之前,即使编译器最终省略了副本,也需要存在复制构造函数。 C++17 更改了规则,在这种情况下不再需要复制构造函数。