复制构造函数和赋值运算符都从一个对象复制到另一个对象,那为什么我们需要两者? Copyconstructor意味着它创建一个新对象并从另一个现有对象复制内容,赋值运算符将内容从一个现有对象复制到现有对象。
所以最终两者都将内容从一个对象复制到另一个对象,那么为什么我们需要两个对象,只有一个对象。
答案 0 :(得分:1)
每次想要复制时,不应仅仅为了在下一步中进行分配而创建虚拟对象。
特别是如果对象构造即使在默认构造时也很昂贵。
但是复制c'tors的最终理由是,用户定义类型的值传递将是不可能的。然后我们将没有RAII。
对于赋值运算符,想象一下如果没有它就编写类。通用(模板)代码看起来如何?
许多通用算法可以对仅可分配的类进行操作,但是如果没有该功能,则必须在再次“构造”对象之前自己调用它们。
template <calls T)
void assign(T& a, T& b)
{
a.~T();
new (&a) (b);
}
基本上,这对他们必须公开的课程提出了不合理的要求。或者他们必须将您的算法设为friend
。
此外,这是不安全的。构造函数可能会抛出,这就是他们报告错误的方式,以及T
复制c'tor是否会执行,而a
在析构函数调用之后处于未定义状态。
问题是你决定将a
的状态从它中解放出来。如果我们使用了赋值运算符,那么仍然会抛出赋值,但它可以确保a
不会释放它的状态。
答案 1 :(得分:1)
因为建筑和作业是不同的东西。复制构造函数涉及,例如,当您按值传递参数或使用另一个构造对象时:
f(T o) {
...}
T object;
f(object); // copy construction to pass the argument
T object2(object); // construct a T from another T
虽然分配是指您已经拥有这两个对象并希望将其中一个复制到另一个对象中,但
T object;
...
T object2;
...
object = object2;
这些事情发生在不同的表达方式上。
答案 2 :(得分:1)
因为它们是不同的东西。
当你想要从另一个构造一个新对象时,将调用复制ctor。
当您想要从另一个对象分配现有对象时,将调用赋值运算符,这意味着您可能需要在执行赋值之前销毁/释放现有对象保留的某些资源。
答案 3 :(得分:0)
这里有两种不同的情况,
在(1)
适用的情况和(2)
适用的地方有不同的情况。他们不一样。
例如,如果我们想要共享资源的所有权(例如内存)拥有一个具有相同类型的另一个对象的对象(shared_ptr就是一个很好的例子),我们需要在该类上实现一个合适的copy-assignment
运算符。
因此,我们需要为复制构造和复制分配提供条件。