C ++中的复制构造函数和赋值运算符

问题描述 投票:0回答:1

[当我学习C ++的构造函数时,我想到了一些我很难完全理解的东西。一种是在创建类的对象(例如class Point)时,如果我们没有为自己编写构造函数,则会调用默认构造函数。(我认为与复制构造函数相同)

Point p2 = p1;

在这种情况下,我得到了默认的拷贝构造函数,但是如果我这样做,该怎么办:

Point p1;
p1.setX(3);
p2.setY(2);

Point p2;

p2 = p1;

这仍然有效,但是我想这里不会调用默认的复制构造函数,因为我认为在创建对象时会调用构造函数。那么在第二种情况下该分配如何工作?

[除此之外,我想知道我们何时编写自己的副本构造函数(ClassName (const ClassName &old_obj);左右)。下面的两个示例之间是否有区别,或者仅仅是语法糖?

Point p3(p1);

Point p3 = p1;

并且在第二个示例中,为什么程序推断我们将p1作为参数传递给复制构造函数,而我们却没有在p3之后在括号内编写它,

此外,当我们创建一个类的对象时,该类的参数将参数传递给其构造函数,我们使用括号将数据作为参数传递。但是,当涉及默认构造函数时(即使我们编写了自己的),我们根本不用括号,而是像这样创建对象:

Point p1;

不是那样:

Point p1(); // even if we defined our default constructor like "Point() {}"

这是什么原因?程序是否知道不为我们创建默认构造函数?

c++ copy-constructor default-constructor
1个回答
0
投票

我在这里假设一个默认的Point实现。

[当我学习C ++的构造函数时,我想到了一些我很难完全理解的东西。一种是当我们创建一个类的对象(例如Point类)时,如果我们不为自己编写一个构造函数,则会调用默认构造函数。(我认为与复制构造函数相同)

点p2 = p1;

在这种情况下,我得到了默认的拷贝构造函数,但是如果我这样做,该怎么办:

真实

点p1;p1.setX(3);p2.setY(2);

Point p2;

p2 = p1;这仍然有效,但是我想这里不会调用默认的复制构造函数,因为我认为在创建对象时会调用构造函数。那么在第二种情况下该分配如何工作?

是。使用赋值运算符。复制构造函数仅在创建新的Point对象时使用。实际上,如果您有副本构造函数,则应该有一个带有实施。

[除此之外,我想知道我们何时编写自己的副本构造函数(ClassName(const ClassName&old_obj);等等)。下面的两个示例之间是否有区别,或者仅仅是语法糖?

如果有特殊之处,您可以编写自己的副本构造函数。也许由于某种原因不应复制成员。也许成员不能使用复制构造函数/赋值构造函数进行复制,而您必须调用非标准的CloneThis方法。如果所有成员都是可复制的并且应该复制所有成员,则只需使用= default。

(我将不进行移动分配/移动构造)

点p3(p1);和

点p3 = p1;在第二个示例中,为什么程序会推断出我们将p1作为参数传递给复制构造函数,而我们却没有在括号内的p3之后编写它呢?

自C ++ 11起,保证是语法糖。保证它们都可以调用复制构造函数。另一种解释是首先调用p3的默认构造函数,然后调用赋值运算符将p1的值分配给p3。这显然是浪费的,并且如果p3不是默认可构造的,甚至是不可能的。

此外,当我们创建一个类的对象时,该类的参数将参数传递给其构造函数,我们使用括号将数据作为参数传递。但是,当涉及默认构造函数时(即使我们编写了自己的构造函数),我们根本不用括号,而是像这样创建对象:

点p1;而不是这样:

Point p1(); //即使我们定义了默认的构造函数,例如“ Point(){}”是什么原因呢?程序是否知道不为我们创建默认构造函数?

您可以编写Point p1;或者您可以编写Point p1 {};

您可以编写Point p1(),但这意味着声明不带参数的函数p1,该函数将返回Point。但是,现代编译器会向您发出有关第三个变体的警告,因为这是一个常见的错误。

现代建议使用{},因为它更加统一。点p1 {};点p2 {1,1};

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.