提问人:alexmoran 提问时间:3/1/2020 最后编辑:David C. Rankinalexmoran 更新时间:3/1/2020 访问量:804
C++ 中的复制构造函数和赋值运算符
Copy Constructors And Assignment Operator in C++
问:
当我在 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;
在第二个例子中,为什么程序推断我们作为参数传递给复制构造函数,而我们没有在 inside parantheses 之后编写它?p1
p3
此外,当我们创建一个类的对象,该对象将参数用于其结构时,我们使用括号将数据作为参数传递。但是当涉及到默认构造函数时(即使我们编写了自己的构造函数),我们根本不使用括号并创建这样的对象:
Point p1;
而不是那样的:
Point p1(); // even if we defined our default constructor like "Point() {}"
这是什么原因?程序是否知道不要为我们创建默认构造函数?
答:
我在这里假设一个默认的 Point 实现。
当我在 C++ 中学习构造函数时,我想到了对我来说很难完全理解的东西。一种是当我们创建一个类的对象(比如类 Point)时,如果我们没有为自己编写构造函数,则会调用默认构造函数。(我认为复制构造函数也一样)
点 p2 = p1;
在这种情况下,我得到了默认复制构造函数的调用,但是如果我这样做怎么办:
真
点 p1; p1.setX(3); p2.setY(2);
点 p2;
p2 = p1; 这仍然有效,但我想默认的复制构造函数不会在这里被调用,因为我认为构造函数在创建对象时被调用。那么,在第二种情况下,该任务如何工作呢?
真。使用赋值运算符。复制构造函数仅在创建新的 Point 对象时使用。在实践中,如果您有一个复制构造函数,则应该有一个带有 Machting 实施。
除此之外,我想知道我们什么时候编写自己的复制构造函数(ClassName (const ClassName &old_obj);下面的两个例子之间有区别还是只是句法糖?
如果有什么特别之处,您可以编写自己的复制构造函数。也许由于某种原因不应该复制成员。也许成员不能使用复制构造函数/赋值构造函数进行复制,并且您必须调用非标准的 CloneThis 方法。 如果所有成员都是可复制的,并且所有成员都应该被复制,则只需使用 = default。
(我将把搬家任务/搬家施工排除在外)
点 p3(p1); 和
点 p3 = p1; 在第二个示例中,为什么程序推断我们将 p1 作为参数传递给复制构造函数,而我们没有将其写在 p3 之后?
由于C++11,它保证是句法糖。它们都保证调用复制构造函数。另一种解释是首先调用 p3 的默认构造函数,然后调用赋值运算符将 p1 的值分配给 p3。这显然是浪费的,如果 p3 不是默认构造的,甚至可能是不可能的。
此外,当我们创建一个类的对象,该对象将参数用于其结构时,我们使用括号将数据作为参数传递。但是当涉及到默认构造函数时(即使我们编写了自己的构造函数),我们根本不使用括号并创建这样的对象:
点 p1; 而不是那样的:
点 p1();即使我们定义了默认构造函数,例如 “Point() {}” 这是什么原因?程序是否知道不要为我们创建默认构造函数?
你可以写 Point p1;或者你可以写 Point p1{};
你可以写 Point p1(),但这意味着声明一个没有参数的函数 p1,它返回一个 Point。 但是,现代编译器会向您发出有关第三种变体的警告,因为这是一个常见的错误。
现代建议使用 {},因为它更统一。 点 p1{}; 点 p2{1, 1};
希望这会有所帮助。
评论
p1
Point
Point
p1
Point p1;
class Point
Point pi();
Point