拷贝构造函数和赋值运算符的区别

difference between copy constructor and assignment operator

我已经完成了 [question] (What's the difference between assignment operator and copy constructor?) 并理解了复制构造函数和赋值运算符之间的区别。现在我的问题是 尽管复制构造函数初始化了之前未初始化的对象,而赋值运算符替换了之前初始化对象中的数据 最终结果有什么不同。我在想这两种情况的最终结果是一样的吧?最后通过 (CC) 复制后我们得到相同的输出,甚至在使用 (AO) 后我们得到相同的输出。我在这里有意义吗?有人可以澄清一下在实际应用方面有什么区别吗?

在复制构造函数中,您正在赋值中创建新对象,您是在同时从其他对象向现有对象赋值。因此输出可能与您实现复制构造函数和赋值运算符函数的方式不同

除了你说的,没有区别。
CC 处理新的统一对象(毕竟它是一个构造函数),操作符处理现有对象。
CC 的使用可以替换为普通构造函数,然后是赋值操作(通常 类),但这不如使用复制数据直接构造高效。
例如

class C
{
private:
    vector<int> v;
public
    C()
    {
        //fill v with 10^9 slowly generated random numbers, takes ca. 2 days
    }
    C(const C& c)  //could be auto-generated in this case
    {
        v = c.v;
    }
    C &operator=(const C& c)  //could be auto-generated in this case
    {
        v = c.v;
        return *this;
    }
};

...

C oldc;

...

//either
C newc(oldc);
//or
C newc; //takes 2 days
newc = oldc;

另一个原因,一些重要的 类 没有(public)默认构造函数,只能通过从某处复制现有对象来创建。

这取决于你。该语言对 关于复制构造函数或赋值实际上做了什么。 当然,任何客户都会期望可观察到的状态 该对象与复制对象的对象相同,在两者中 案例;这包括标准库中的代码,可以复制 或分配给您的对象类型。但也有合法的案例 其中 class 可能包含元信息,用于 仪器或资源管理,这可能是不同的 在这两种情况下。 (class 支持也很常见 复制构造,用于 clone 函数,但不用于 支持赋值。)

当然,实现方式可能大不相同;如果 对象包含指向动态分配内存的指针,对于 示例:

class Toto
{
    Titi* myPtr;
public:
    Toto() : myPtr( new Titi ) {}
    Toto( Toto const& other ) : myPtr( other.myPtr->clone()) {}
    ~Toto() { delete myPtr; }
    Toto& operator=( Toto const& other )
    {
        Titi* tmp = other.myPtr->clone();
        delete myPtr;
        myPtr = tmp;
        return *this;
    }
};

(在这种简化的情况下,当然,你不会使用 一个指针,只让 class 包含一个实例 Titi。在更复杂的情况下,Titi 实际上是一个 abstract base class, 和你实例化不同的derived classes 根据构造函数的一些参数, 然而,这样的事情可能是合理的。)

最终结果完全视情况而定。你只需要明白

  1. 复制构造函数在从现有对象创建新对象时调用,作为现有对象的副本。

  2. 当两个对象都已创建并且我们正在将一个对象分配给另一个对象时,将调用赋值运算符。 例如: a = b

区别:

  • 复制构造函数创建一个新对象,该对象具有原始对象的副本。

  • 另一方面,赋值运算符不会创建任何新对象。相反,它处理现有对象。

对于指针复制,我们需要深复制,因为编译器的默认复制构造函数和赋值运算符会浅复制。所以检查这个以获得更深入的理解 Shallow copy vs Deep copy

我相信您已经找到了很多关于复制构造函数和赋值运算符之间的区别的帖子,或者至少是它们的默认行为(如果您重载它们,您可以做的事情没有限制......或中断)。所以我将把我的回答限制在你关于最终结果的具体问题上。

调用它们中的任何一个的结果是你最终得到初始化(或重新初始化)的数据或对象......然而,还有更多,因为它们在不同的情况下被调用并且对内存的影响不同。无需深入讨论可能的不良行为、堆栈使用、浅拷贝与深拷贝(处理指针时需要注意这一点),拷贝构造函数将创建对象的新实例并拷贝数据给它,而赋值运算符与已经存在的 copy 一起工作。

我希望这能回答你的问题...