通过示例理解复制构造函数和赋值操作符

Understanding copy constructors and assignment operators with an example

本文关键字:复制 构造函数 赋值操作符      更新时间:2023-10-16

我最近一直在阅读《c++ with Qt 4设计模式介绍》这本书,我对下面的例子感到困惑(代码来自书中,我自己做了一点修改):

"fraction.h"

class Fraction
{
public:
    Fraction(int n, int d): m_Numer(n), m_Denom(d) {
        ++ctors;
    }
    Fraction(const Fraction& other)
        : m_Numer(other.m_Numer), m_Denom(other.m_Denom) {
        ++copies;
    }
    Fraction& operator = (const Fraction& other) {
        m_Numer = other.m_Numer;
        m_Denom = other.m_Denom;
        ++assigns;
        return *this;
    }
    Fraction multiply(Fraction f2) {
        return Fraction (m_Numer*f2.m_Numer, m_Denom*f2.m_Denom);
    }
    static void report();
private:
    int m_Numer, m_Denom;
    static int assigns;
    static int copies;
    static int ctors;
};
"main.cpp"

#include <iostream>
#include "fraction.h"
using namespace std;
int Fraction::assigns = 0;
int Fraction::copies = 0;
int Fraction::ctors = 0;
void Fraction::report()
{
    cout<<"[assigns: "<<assigns<<", copies: "<<copies<<", ctors: "<<ctors<<"]nn";
}
int main()
{
    Fraction twothirds(2, 3); // It calls a constructor
    Fraction threequarters(3, 4); // It calls a constructor
    Fraction acopy(twothirds); // It calls a copy constructor
    Fraction f4 = threequarters;  
    // [Question A]: The book says it's using a copy constructor 
    //               but I don't see how. Isn't it an assignment?
    cout<<"after declarationsn";
    Fraction::report();  //output: [assogns: 0, copies: 2, ctors: 2]
    f4 = twothirds;  // It's an assignment using the assignment operator
    cout<<"before multiplyn";
    Fraction::report();  //output: [assogns: 1, copies: 2, ctors: 2]
    f4 = twothirds.multiply(threequarters);
    cout<<"after multiplyn";
    Fraction::report();  //output: [assogns: 2, copies: 3, ctors: 3]
    // [Question B]: How does the frunction "multiply" creates three Fraction objects?
    return 0;
}

根据我在main.cpp留下的评论,我有两个问题。

[问题A]:为什么Fraction f4 = threequarters使用复制构造函数而不是赋值?

[问题B]:函数"乘法"如何创建三个Fraction对象?

特别是问题B,我想不出这三个东西是从哪里来的。

请帮助我理解这些概念。

问题A:为什么Fraction f4 = three/quarters使用复制构造函数而不是赋值?

答案A:这是c++语言的定义。如果你用了

Fraction f4;
f4 = threequarters; 

则第二行使用赋值操作符

问题B:函数"乘法"如何创建三个Fraction对象?

答案B:

当你调用multiply时,参数f2是通过复制构造创建的。

return Fraction (m_Numer*f2.m_Numer, m_Denom*f2.m_Denom);

使用正则构造函数构造对象。

f4 = twothirds.multiply(threequarters);

multiply构造的对象赋值给f4

问题A:因为在一行Fraction f4 = threquarters中,f4还不存在,所以调用复制构造函数来创建一个" threquarters "的副本。操作符=只在对象已经存在时调用。F4 =三分之二)

问题B: Fraction multiply(Fraction f2),当执行twothirths .multiply(threquarters)时,函数调用参数是"按值传递"的(即。将副本传递给函数)。所以在这个例子中,复制了一个"threequarters"并传递给"multiply"。然后在该函数内部通过调用构造函数显式地创建了一个Fraction。最后,您将其作为Fraction返回,这意味着返回了它的副本。所以整个函数调用进行了1次复制构造函数调用来传递它,1次构造函数调用来创建Fraction, 1次复制构造函数调用来返回Fraction,总共3次