首页 > 代码库 > C++知识点:拷贝构造函数例子

C++知识点:拷贝构造函数例子

//拷贝构造函数:
//函数参数传递时调用一次拷贝构造函数,给对象赋值时调用一次拷贝构造函数,对象作为参数传递后会被及时销毁。
#include <fstream>
#include <string>
using namespace std;
ofstream out("HowMany2.out");

class HowMany2
{
    string name;//object identifier
    static int objectCount;
public:
    HowMany2(const string& id = "") : name(id)
    {
        ++objectCount;
        print("HowMany2()");
    }
    ~HowMany2()
    {
        --objectCount;
        print("~HowMany2()");
    }
    // the copy-constructor;
    HowMany2(const HowMany2& h) : name(h.name)
    {
        name += " copy";
        ++objectCount;
        print("HowMany2(const HowMany2&)");
    }
    void print(const string& msg = "") const
    {
        if (msg.size() != 0)
        {
            out << msg << endl;
        }
        out << \t << name << ":" << "objectcount=" << objectCount << endl;
    }
};

int HowMany2::objectCount = 0;
//pass and return By value:
HowMany2 f(HowMany2 x)
{
    x.print("x argument inside f()");
    out << "Returning from f()" << endl;
    return x;
}

int main()
{
    HowMany2 h("h");
    //1.HowMany2()
    //2.h:objectCount = 1
    out << "Entering f()" << endl;
    //3.Entering f()
    /*进入f(h)
    此时拷贝构造函数被编译器调用,完成传值过程,
    在f()内创建了一个新对象,他是h的拷贝,所以对象变成2
    输出:
    //传递对象作为函数参数时即发生拷贝构造
    4.HowMany2(const HowMany2&)
    5.h copy :objectcount=2
    6.x argument inside f()
    7.h copy:objectcount=3
    8.returning from f()
    第8显示了从f()返回的开始情况,但在局部变量“h拷贝”销毁前
    (在函数结尾这个局部变量出了范围)他必须被拷入返回值,也就是h2.
    以前未创建的对象h2是从现在的对象(在函数f()内的局部变量创建的)
    所以在第9行拷贝构造函数又被调用了。
    现在对于h2的标识符,名字变成了h拷贝的拷贝,因为他是从拷贝拷过来的,
    这个拷贝是函数f()内部对象,
    在对象返回之后,函数结束之前,对象数暂时变为3,但是此后h拷贝被销毁。

    */
    HowMany2 h2 = f(h);
    //在完成对f()的调用后,仅有两个对象h和h2,这是看到h2最终是h拷贝的拷贝
    h2.print("h2 after call to f()");
    out << "call f() , no return value" << endl;
    //从第15行开始调用f(h),这次调用忽略了返回值,在16行可以看到恰好在参数传入之前,
    //拷贝构造函数被调用。和前面一样,21行显示了为了返回值而调用拷贝构造函数。但是拷贝构造函数必修
    //有一个作为它的目的地址(this指针)的工作地址,但这个地址从哪里来呢?
    //每当编译器为了正确地计算一个看不见的对象而需要一个临时对象时,编译器都会创建一个,在这种情况下
    //编译器创建一个看不见的对象作为函数f()忽略了的返回值的目标地址。这个临时对象的生存期应该尽可能的短暂,
    //这样空间就不会被这些等待被销毁的而且占用资源的临时对象搞乱。在一些情况下,临时对象可能立刻被传递给
    //另外的函数,但是现在这种情况下临时对象不再需要,所以一旦调用完毕就对内部对象调用析构函数(23-24)
    //这个临时对象被销毁(25-26)
    //28-31行,h2,h被销毁
    f(h);
    out << "After call to f()" << endl;
}
//输出结果:
/*
1.HowMany2()
2.h:objectCount=1
3.Entering f()
//传递对象作为函数参数时即发生拷贝构造
4.HowMany2(const HowMany2&)
5.h copy :objectcount=2
--------------------------
6.x argument inside f()
7.h copy:objectcount=3
8.returning from f()
//返回对象再次调用拷贝构造函数
--------------------------
9.HowMany2(const HowMany2&)
10.h copy copy: objectCount=3
//临时对象使用完毕,析构
11.~HowMany2()
12.h copy : objectcount=2
13.h2 after call to f()
14.h copy copy: objectCount=2
15.call f(),no return value
//f(h)
16.HowMany2(const HowMany2&)
17.h copy: objectcount=3
18.x argument inside f()
19.h copy:objectCount=3
20.Returning from f()
//f(h)后赋值给未知的值,在此调用拷贝构造函数
21.HowMany2(const HowMany2&)
22.h copy copy:objectCount = 4
//临时对象使用完毕再次调用析构函数
23.~HowMany2()
24.h copy : objectCount = 3
//销毁匿名的对象
25.~HowMany2()
26.h copy copy:objectCount=2
27.After call to f()
28.~HowMany2()
29.h copy copy :objectcount=1
30.~HowMany2()
31.h: objectcount=0
*/

 

C++知识点:拷贝构造函数例子