【问题标题】:Constructor calls during assignment operations and object passing赋值操作和对象传递期间的构造函数调用
【发布时间】:2013-03-14 10:40:50
【问题描述】:

我对通过引用传递对象和通过值传递给特定类的函数之间的区别感到困惑。如果我按值传递对象,我知道默认的复制构造函数会生成对象的逐个成员副本,以便在给定函数中使用。但是,如果我将对象作为需要深度复制的类的 const 引用传递,是否仍会调用复制构造函数?说我有一个函数

     void debug(const MyClass& object1); 

传递 object1 会调用复制构造函数吗?还是直接将对象传递给函数而不进行复制?还有一个问题 - 如果我有一个名为 Fraction 的课程-

     Fraction A(1,2); // 1 is this numerator, 2 the denominator

     A = Fraction(2,3);

上述行是否调用了默认构造函数来创建一个临时对象 Fraction(2,3),然后是赋值运算符?

谢谢。

【问题讨论】:

    标签: c++


    【解决方案1】:

    Would passing object1 call the copy constructor?

    不,它不会调用复制构造函数,因为它是通过引用传递的 在这种情况下没有复制

    A = Fraction(2,3);
    

    是的,它会调用带有两个参数的构造函数(如果两个参数都有默认值,则调用默认构造函数),然后调用复制赋值运算符。

    你可以看到下面代码的输出:

     #include <iostream>
     using namespace std;
     class Fraction
     {
      public:
      int denom;
      int nominator;
      Fraction(int d , int n ):denom(d), nominator(n)
      {
        cout << "call non-copy constructor" <<endl;
      }
    
      Fraction(const Fraction&  rhs)
      {
        cout << "call copy constructor" <<endl;
        denom = rhs.denom;
        nominator = rhs.nominator;
      }
    
      const Fraction& operator=(const Fraction&  rhs)
      {
       cout << "call copy assignment operator" << endl;
       if (this == &rhs)
       {
          return *this;
       }
    
       denom = rhs.denom;
       nominator = rhs.nominator;
       return *this;
       }
    };
    
    void debug(const Fraction& obj)
    {
      cout << "this is debug: pass by reference " <<endl;
    }
    
    void debugPassByValue(Fraction obj)
    {
      cout << "this is debug: pass by value" <<endl;
    }
    
    int main()
    {
      Fraction A(1,2);
      cout << "--------------" <<endl;
      debug(A);
      cout << "--------------" <<endl;
      A = Fraction(2,3);
      cout << "--------------" <<endl;
      debugPassByValue(A);
      cout << "--------------" <<endl;
      cin.get();
      return 0;
    

    }

    您将看到以下输出:

    call non-copy constructor  //Fraction A(1,2);
    --------------
    this is debug: pass by reference  //debug(A);
    --------------
    call non-copy constructor    //A = Fraction(2,3);---> construct temporary object
    call copy assignment operator  //A = Fraction(2,3);
    --------------
    call copy constructor   //debugPassByValue(A);
    this is debug: pass by value
    --------------
    

    现在您将更清楚地了解所调用的内容。

    【讨论】:

      【解决方案2】:

      下面我们将考虑[x] 表示x 是可选的。

      我对通过引用传递对象和通过值传递给特定类的函数之间的区别感到困惑。

      当你通过值传递一个对象时,程序必须创建函数的本地对象,因此它调用类的复制构造函数来创建这个对象。当您通过引用(并且看似通过指针)传递时,函数内部的变量object1 只是您传递给函数的对象的别名;因此,如果您在函数内部编辑那个,编辑也将应用于外部对象。

      上述行是否调用了默认构造函数来生成一个临时对象 Fraction(2,3),然后是赋值运算符?

      这是赋值运算符。考虑到A 是一个已经声明的X 类型的变量,它将被称为X Fraction::operator=([const] Fraction[&amp;]) 或任何兼容的类型。

      注意:当声明Fraction x = Fraction(2, 3) 时,它不会像您所期望的那样使用operator=,而是会调用相应的构造函数(在这种情况下为Fraction::Fraction([const] Fraction[&amp;]))。 p>

      【讨论】:

      • 所以,为了我自己的启迪,通过引用传递对象或作为 const 引用传递给函数不会调用复制构造函数。在任何一种情况下,对象都是别名,唯一的区别是 const 引用不会是可变的。这是正确的吗?
      • @Jonnywalkerr,是的,没错。实际上,const 引用的 const 部分可以很容易地用 constant_cast 向下转换,但是是的,它不应该是可变的。
      【解决方案3】:

      debug 的情况下确实没有复制。

      在第二种情况下,我不太确定我是否理解您的问题。这一行:

      A = Fraction(2,3);
      

      应该使用Fraction 的赋值运算符。 A 已经存在,所以它使用实例A 上的赋值运算符来分配它Fraction(2,3),这是一个临时对象。

      【讨论】:

      • 对不起,我不是很明确。我真的很想知道在通过默认赋值运算符将临时对象 Fraction(2,3) 分配给 A 之前,是否调用了构造函数来构造临时对象。
      猜你喜欢
      • 2019-11-16
      • 1970-01-01
      • 2015-08-18
      • 2021-12-16
      • 2020-05-24
      • 1970-01-01
      • 2018-05-07
      • 2014-10-24
      • 1970-01-01
      相关资源
      最近更新 更多