【问题标题】:Default Constructor Calls默认构造函数调用
【发布时间】:2013-03-13 17:21:27
【问题描述】:

我正在使用模拟考试来准备 C++ 考试。我在确定何时调用某些构造函数时遇到问题。代码是 -

using namespace std;
#include <iostream>

class Fraction
{
  private:
   int numerator, denominator;
  public:
   Fraction( int = 0, int = 1 );
   friend ostream& operator<<( ostream&, const Fraction& );
  };

 void debug( Fraction, Fraction );
 Fraction task( Fraction&, const Fraction& );

int main()
  {
    Fraction * A[6], * B; // Line 1
    Fraction C( 3 ), D( C ); // Line 2
    Fraction E[4], F = D; // Line 3
    Fraction G, H( 3, 4 ); // Line 4
    debug( C, D ); // Line 5
    B = new Fraction; // Line 6
    F = task( H, C );
    delete B;
    return 0;
  }

 void debug( Fraction X, Fraction Y )
 {
   cout << X << endl << Y << endl;
 }

 Fraction task( Fraction& X, const Fraction& Y )
 {
   Fraction Z;
   Z = Fraction( 5, 2 ); // Line 7
   return 1; // Line 8
 }

现在,我认为在 3 种类型的实例中调用了默认的复制构造函数。

示例 1 -

        Fraction A(1,2);

        Fraction B(A);

示例 2 -

        Fraction A(1,2);

        Fraction A = B;

3 - 从函数返回对象时

4 - 当一个对象作为参数传递给函数时

有两个问题我似乎无法回答 -

问题 1 - 考虑上面的源代码。当。。。的时候 标记为“第 3 行”和“第 4 行”的语句被编译并执行,有多少 将为每个“分数”类的构造函数调用 那些陈述?

答案是 - D) 第 3 行:5 次调用 第 4 行:2 次调用

这个问题的答案是 D。但是,当我回答它时,我得到了不同的结果 -

    Fraction E[4], F = D; // Line 3

我看到数组E[4]的默认构造函数被调用了5次,但我认为这个语句也相当于-

    Fraction E[4], Fraction F(D);

因此,默认构造函数被调用 5 次,复制构造函数被调用一次。显然,这是不正确的,因为构造函数只被调用了 5 次。我没有看到我的错误在哪里。

我的另一个问题是在以下问题中 -

  1. 考虑图 2 中的源代码(上一页)。当。。。的时候 标记为“第 7 行”和“第 8 行”的语句被编译并执行,有多少 将为每个“分数”类的构造函数调用 那些陈述?

    答案是 - D) 第 7 行:1 次呼叫 第 8 行:1 次呼叫

        Fraction task( Fraction& X, const Fraction& Y )
        {
          Fraction Z;
          Z = Fraction( 5, 2 ); // Line 7
          return 1; // Line 8
        }
    

    我原本以为会调用默认构造函数为Fraction(5,2)创建一个临时对象,然后复制构造函数将Fraction(5, 2)复制到Z。这实际上是对默认赋值的操作吗操作员?至于第 8 行,这是否是因为它返回了 Fraction 类型的对象而调用了复制构造函数?

我在这里还有几个问题 -

会 -

debug(B, C)

调用复制构造函数两次以传递 Fraction 对象 B 和 C 的副本?

并且是 -

F = task( H, C );

调用默认赋值运算符以及F已经作为初始化的Fraction对象存在?

【问题讨论】:

  • 为什么不在调试器中运行这段代码?
  • 对不起,如果这不能回答您的问题。该程序正在使用默认构造函数。我试图记下默认构造函数何时被调用。如果有一个调试器会告诉我,那就太好了。但是,我想了解为什么我的电话比分配的问题的答案要多。与第 3 行一样,我计算的呼叫比答案多一个。我的逻辑有些问题。
  • 你的代码能编译吗?至少在 g++ 4.7.2 上没有
  • 我不确定。这只是我教授网页上发布的练习考试的示例代码。据推测,它应该编译。

标签: c++


【解决方案1】:

你基本上想知道什么时候调用默认构造函数和复制构造函数。

第一个问题:

Fraction E[4], F = D; // Line 3

E[4] 是一个 Fraction 对象数组,它调用默认构造函数 4 次,因为您没有显式调用任何其他构造函数来初始化这些对象。由于在第 2 行对象 D 已经构造,因此,F 是使用复制构造函数构造的,在这种情况下,编译器会为您生成一个,因为您没有为自己定义一个。 所以在这种情况下,有 4 个默认构造函数调用和 1 个复制构造函数调用。 在第 4 行,两个对象都调用了默认构造函数,因此在默认 ctor 上调用了两次。

debug(B, C)
call the copy constructor twice to pass copies of Fraction objects B and C?

是的,由于debug函数中参数是按值传递的,所以BC都调用了复制构造函数

一般来说,复制构造函数在以下情况下被调用:

  1. 使用现有对象(如F= DF(D))实例化一个对象时
  2. 按值传递对象时。
  3. 当对象按值从函数返回时。

希望这能为您提供足够的信息来理解代码。

【讨论】:

  • 谢谢。似乎我忘记了声明数组的容量是显式的,而不是元素的数量 + 1。如果我可能会问,假设我声明了 Fraction F(1,2),然后将现有对象复制到其中,例如F = 分数 (3,4)。这会调用默认构造函数和默认赋值运算符吗?
  • @Jonnywalkerr Fraction F(1,2) 将调用默认构造函数,F(3,4) 也会调用默认构造函数。由于 F 已经创建,F =Fraction(3,4) 将调用复制赋值运算符,在这种情况下编译器会为您生成。
  • 因此,编译器会生成一个复制构造函数和一个复制赋值运算符。调用复制构造函数来处理将数据成员从对象逐个成员复制到新声明的对象。这个和默认赋值运算符的区别在于赋值运算符将项目从一个对象复制到一个已经初始化的对象。它是否正确?此外,对于 F = Fraction(3,4) 之类的东西,是否只有复制赋值运算符被调用?或者是否也调用了默认构造函数来生成临时对象 Fraction(3,4)?
  • @Jonnywalkerr 是的,你基本上明白了。 F= Fraction(3,4) 会先调用默认ctor创建一个临时对象,然后调用复制赋值运算符赋值给F,这里不涉及复制构造函数。
  • 复制赋值运算符是否被视为“构造函数”。根据这个练习考试,F= Fraction(3,4) 将调用单个构造函数。这会是创建临时对象的默认构造函数吗?
猜你喜欢
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多