【问题标题】:difference between copy constructor and assignment operator复制构造函数和赋值运算符的区别
【发布时间】:2015-03-03 23:23:33
【问题描述】:

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

【问题讨论】:

  • @deviantfan :假设我已经处理了一个对象并进行了一些处理。现在在我的程序的末尾,我在一个对象上使用复制构造函数,并在另一个对象上使用赋值运算符,然后使用 print function 来查看值。在这两种情况下,输出都将是相同的,因为两者都在复制我之前在程序中处理的相同对象?!
  • 如果你有一个理智的 CC,是的。重要的区别是,如果您创建一个新对象只是为了在下一行中分配一些东西,那么普通的构造函数可能会不必要地浪费时间(和内存)。在下面添加了一个示例。

标签: c++ constructor assignment-operator


【解决方案1】:

最终结果完全取决于情况。你只需要明白这一点

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

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

区别:

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

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

对于指针复制,我们需要 深复制 作为编译器的默认复制构造函数,而赋值运算符则需要 浅复制。因此,请查看此内容以更深入地了解Shallow copy vs Deep copy

【讨论】:

    【解决方案2】:

    我敢肯定你已经找到了几十篇关于复制构造函数和赋值运算符之间区别的帖子,或者至少是它们的默认行为(如果你重载它们,你可以做的事情没有限制......或破坏)。所以我的回答仅限于你关于最终结果的具体问题。

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

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

    【讨论】:

      【解决方案3】:

      这取决于你。语言没有要求 关于复制构造函数或赋值的实际作用。 当然,任何客户都会期望观察到的状态 对象与复制对象的对象相同,在两者中 案例;这包括标准库中可以复制的代码 或分配给您的对象类型。但也有合法的案例 其中类可能包含元信息,用于 仪器或资源管理,这可能是不同的 在这两种情况下。 (一个类也经常支持 复制构造,用于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;
          }
      };
      

      (当然,在这种简化的情况下,您不会使用 一个指针,并且只让类包含一个实例 Titi。在更复杂的情况下,Titi 实际上是 抽象基类,你实例化不同的派生类 根据构造函数的一些参数进行类, 然而,这样的事情可能是合理的。)

      【讨论】:

        【解决方案4】:

        除了你说的,没有区别。
        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;
        

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

        【讨论】:

        • 所以在编码方面也不会有任何区别吧?!在这里,您已经给出了自己的复制构造函数。如果您还要重载赋值运算符。编码逻辑或多或少是一样的吧?!
        • @tanz 哇,忘记添加了。但是,是的,在这种情况下,没有真正的区别。它可能会有所作为,例如。当您在构造函数中使用 malloc/new 分配某些内容时:CC 也必须分配,操作员可以依赖它已经存在。或者如果构造函数创建一个线程或修改一些对象计数器或......
        • @deviantfan 实际上,复制构造函数的作用和赋值的作用之间没有特别的关系,除了你作为程序员定义的那个。
        • @JamesKanze 这就是我写“理智”的原因
        • @deviantfan 但是你错过了重要的一点:让课程以理智的方式表现得由课程的作者决定; C++ 中没有任何东西需要它。 (此外,还有一些特殊情况,对象的内部状态会根据它是复制构造还是分配而有所不同。想想使用计数:复制构造函数会将其设置为 0,而不管其值如何在源代码中,并且赋值运算符不会修改它。)
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2014-05-18
          • 2012-07-27
          • 2011-07-19
          • 1970-01-01
          • 1970-01-01
          • 2013-04-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多