【问题标题】:What special member function is used for copy initialization in c++?c++中复制初始化使用什么特殊的成员函数?
【发布时间】:2022-01-02 08:08:10
【问题描述】:

我正在测试 c++ 类初始化。

class Point
{
private:
    int x,y;
public:
    Point() = delete;
    Point(int a):x(a), y(0) { std::cout << "Conversion" << std::endl;}
    
    Point(const Point&) { std::cout << "Copy constructor" << std::endl;}
    //Point(const Point&) = delete;
    Point& operator=(const Point&) = delete;

    Point(Point&&) = delete;
    Point& operator=(Point&&) = delete;
};

int main()
{
    Point p1(5); //case1
    Point p2 = 5; //case2

    return 0;
}

在上面的代码中,我认为“5”首先会被case1/2的转换构造函数转换为临时对象。然后,我预计必须使用复制构造函数来初始化 p1 和 p2。但是,事实并非如此。 当我运行这段代码时,我在控制台中只看到了两条“转换”消息。没有“复制构造函数”消息。

尽管我删除了所有复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符,但这段代码运行良好。

如果您告诉我在为“5”创建临时对象后将使用什么特殊成员函数进行初始化,我将不胜感激,

我正在使用带有 std=c++17 选项的 g++ 编译器。

【问题讨论】:

  • 您的复制构造函数不会复制,因为它无法复制 xy 成员,因此它是错误的。不要编写存根复制构造函数、赋值运算符等代码。如果您编写此类函数,请完成它们。
  • @Ted Lyngmo 感谢您提供适当的标签。
  • @PaulMcKenzie 是的,你是对的。此代码不完整。我只想检查构造函数的行为。但我会听从你的建议。谢谢。

标签: c++ constructor initialization c++17 copy-constructor


【解决方案1】:

案例一

在情况 1 中使用 converting constructor,因为您提供了一个可以将 int 转换为 Point 的构造函数。这就是为什么这个构造函数被称为转换构造函数的原因。

案例二

来自mandatory copy elison

在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象直接构建到存储中,否则它们将被复制/移动到。 复制/移动构造函数不需要存在或可访问

在对象的初始化中,当初始化表达式是与变量类型相同的类类型(忽略cv-qualification)的prvalue时。

在情况 2 中,即使您 delete 复制/移动构造函数,也只会使用转换构造函数。这是由于上面引用的强制复制 elison(在 C++17 中)。

【讨论】:

  • 根据cppreference,在复制初始化的情况下,即使发生省略,也需要可以访问适当的构造函数。这似乎与观察到的行为不匹配,即删除复制和移动构造函数仍然允许发生省略。编辑:哎呀,我没有意识到该段落有“(直到 C++17)”标签并反映了预先强制性的省略规则。
  • @Anoop Rana 谢谢你的回答。在我看来,这种复制省略看起来与 RVO 非常相似。我认为 C++17 可以使用这种强制复制省略,所以我在 c++14 测试了相同的代码。当我用 std=c++14 选项编译这段代码时,最后我得到了一个错误,因为删除了 Point(Point &&) 的函数。但是有很奇怪的事情。我将移动构造函数定义为Point(Point&amp;&amp;) { std::cout &lt;&lt; "Move constructor" &lt;&lt; std::endl;},编译完成。但是当我运行代码时,我仍然能够看到 2 条“转换”消息。
  • @bugcreator 您仍然会看到 2“转换”,因为 C++17 之前的编译器允许直接构造到存储中。请注意我上一句中的 allowed to 一词。这并不意味着他们被要求。因此,实际上大多数编译器(在 C++17 之前)过去常常避开复制/移动构造,因为它们被允许这样做。另一方面,在 C++17 中,它们是必需的
  • 我认为这是@Nathan Pierson 提到的情况。虽然省略了 Move Constructor,但它必须在 c++14 中可以访问。
  • @AnoopRana 非常感谢您的友好回答。
猜你喜欢
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多