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
*/
时间: 2024-11-08 20:15:10

C++知识点:拷贝构造函数例子的相关文章

初学C++-----------------类的拷贝构造函数

拷贝构造函数能够使类具有自行赋值本类对象的能力,即可生成一个对象的副本,它只以本类对象的引用作为其唯一的形参,该函数的定义形式如下: class  类名 { public: 类名(形参)://(构造函数) 类名(类名  &对象名)://(拷贝构造函数) .................. }; 类名::类名(类名  &对象名)//拷贝构造函数的实现 { 函数体 } 拷贝构造函数举例: class Point { public: Point(int xx=0,int yy=0)   //构

《C++编程思想》 第十章 引用和拷贝构造函数(知识点+习题+解答)

一.相关知识点 使用引用时有一定的规则: 1) 当引用被创建时,它必须被初始化.(指针则可以在任何时候被初始化.) 2) 一旦一个引用被初始化为指向一个对象,它就不能被改变为对另一个对象的引用.(指针则可以在任何时候指向另一个对象.) 3) 不可能有NULL引用.必须确保引用是和一块合法的存储单元关连. 仅当准备用传值的方式传递类对象时,才需要拷贝构造函数.如果不需要这么做,就不要拷贝构造函数. 对于指向一个对象的指针新的语法变为 ->*,对于一个对象或引用则为.*. 二.相关代码 1. /*R

关注C++细节——含有本类对象指针的类的构造函数、析构函数、拷贝构造函数、赋值运算符的例子

本例只是对含有本类对象指针的类的构造函数.析构函数.拷贝构造函数.复制运算符使用方法的一个简单示例,以加深对构造函数和拷贝控制成员的理解. 读C++ primer 5th 第13章后加上自己的理解,完整的写了下课后习题的代码. 第一版: #include <string> #include <iostream> using namespace std; class TreeNode{ private: string value; TreeNode *left; TreeNode *

从一个例子讲解拷贝构造函数与return

1 #include "iostream" 2 using namespace std; 3 4 5 class Location 6 { 7 public: 8 Location(int xx = 0, int yy = 0) 9 { 10 X = xx; Y = yy; 11 cout << X << "," << Y << " Constructor Object." << end

【转载】C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #include <iostream>using namespace std;class CExample {private:     int a;public:     CExample(int b)     { a=b;}     void Show ()     {        cout<

C++拷贝构造函数(深拷贝,浅拷贝)

http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 #include <iostream> 2 using namespace std; 3 4 class CExample { 5 private: 6 int a; 7 public: 8

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员)、拷贝构造函数

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员).拷贝构造函数  从概念上将,可以认为构造函数分为两个阶段执行: 1)初始化阶段: 2)普通的计算阶段.计算阶段由构造函数函数体中的所有语句组成. 一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 1.对象成员及其初始化 <span style="font-size:14px;">#include <iostream> using namespace std;

拷贝构造函数和赋值操作符

假设有一个如下的MyClass类: class MyClass { public: //构造函数 //拷贝构造函数 MyClass(const MyClass& that) : int_data_(that.int_data_), dbl_data_(that.dbl_data_), str_data_(that.str_data_) { } //赋值操作符 MyClass& operator = (const MyClass& that) { if(this != that) {

构造函数和拷贝构造函数

构造函数,顾名思义,新构造一个对象.如下调用的就是普通的构造函数: String s="cde"; 拷贝构造函数,顾名思义,也是一种构造函数,特殊的构造函数,用一个已存在的对象初始化一个新的对象,就是拷贝构造函数.如下调用的就是拷贝构造函数,用已经存在的string s去初始化新的对象a: String a(s);String a=s; 拷贝构造函数声明如下:(以String为例子) String(); //constructor String(const char *s); //co