zoukankan      html  css  js  c++  java
  • 拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,它在创建对象时,使用的是同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

    l  通过使用另一个同类型的对象来初始化新创建的对象;

    l  复制对象把它作为参数传递给函数;

    l  复制对象,并从函数返回这个对象。

    如果类中没有定义拷贝构造函数,编译器会自行定义一个。如果类中带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数最常见的形式如下:

    classname(const classname &obj)
    {
        //构造函数主体
    }

    在这里,obj是一个对象的引用,该对象是用于初始化另一个对象的。

    /***
    copy_constructor.cpp
    ***/
    #include<iostream>
    using namespace std;
    
    class Line
    {
        public:
            Line(int len);
            Line(const Line & obj);
            ~Line();    
            int getLength(void);
        private:
            int *ptr;
    };
    
    Line::Line(int len)
    {
        cout << "call construct func" << endl;
        //allocate memory for pointer    
        ptr = new int;
        *ptr = len;
    }
    
    Line::Line(const Line &obj)
    {
        cout << "call copy constructor func and allocate memory for point" << endl;
        ptr = new int;
        *ptr = *obj.ptr;
    }
    
    Line::~Line(void)
    {
        cout << "free memory" << endl;
        delete ptr;
    }
    
    int Line::getLength(void)
    {
        return *ptr;
    }
    
    void display(Line obj)
    {
        cout << "the size of line : " << obj.getLength() << endl;
    }
    
    int main()
    {
        Line line(10);
        display(line);
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

    call construct func

    call copy constructor func and allocate memory for point

    the size of line : 10

    free memory

    free memory

    void display(Line obj) //通过gdb调试,该程序在 Line obj处进入拷贝函数构造。

    如果使用以下的main

    int main()
    {
        Line line1(10);
        Line line2 = line1;
    
        display(line1);
        display(line2);
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

    call construct func

    call copy constructor func and allocate memory for point

    call copy constructor func and allocate memory for point

    the size of line : 10

    free memory

    call copy constructor func and allocate memory for point

    the size of line : 10

    free memory

    free memory

    free memory

    在C++中,对象以值传递的方式传入函数参数:

    /***
    value_transf.cpp
    ***/
    #include<iostream>
    using namespace std;
    
    class CExample
    {
        public:
            CExample(int b)
            {
                a = b;
                cout << "create: " << a << endl;
            }
            
            //copy constructor
            CExample(const CExample& C)
            {
                a = C.a;
                cout << "copy constructor" << endl;
            }
    
            //destructor
            ~CExample()
            {
                cout << "delete: " << a << endl;
            }
    
            void show()
            {
                cout << a << endl;
            }
        private:
            int a;
    };
    
    void g_Fun(CExample C)
    {
        cout << "test" << endl;
    }
    
    int main()
    {
        CExample test(1);
        g_Fun(test);
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190806$ g++ value_transf.cpp -o value_transf -g

    exbot@ubuntu:~/wangqinghe/C++/20190806$ ./value_transf

    create: 1

    copy constructor

    test

    delete: 1

    delete: 1

    调用g_Fun()时,会产生以下几个重要的步骤:

    1) test对象传入形参时,会先产生一个临时变量,暂且称呼C

    2) 然后调用拷贝构造函数把test值给C。这两个步骤很像:CExample C

    3) 等g_Fun()执行完后,析构掉C对象。

    拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象把它进行初始化时,将显示使用拷贝构造函数或从函数返回该类型的对象时,将隐式调用拷贝构造函数。

    C++支持两种初始化形式:

    拷贝初始化:int a = 5;和直接初始化 int a(5);

    对于其他类型没有什么区别,对于类类型直接初始化直接调用实参匹配的构造函数,拷贝构造初始化总是调用拷贝构造函数,也就是说

    A x(2);  //直接初始化,调用构造函数

    A y = x; //拷贝初始化,调用拷贝构造函数。

    必须定义拷贝构造函数的情况:

    只包含类类型成员或内置类型(但不是指针类型)成员的类,无须显示地定义拷贝构造函数也可以拷贝;有的类有一个数据成员是指针,或者是由成员表示在构造函数中分配的其他资源,这两种情况下都必须定义拷贝构造函数。

    以下情况使用拷贝构造函数:

    类的对象需要拷贝时,拷贝构造函数将会调用。以下情况都会调用拷贝构造函数:

    l  一个对象以值传递的方式进入函数体

    l  一个对象以值传递的方式从函数返回

    l  一个对象需要通过另外一个对象进行初始化

  • 相关阅读:
    Java1.7的HashMap源码分析-面试必备技能
    Springboot集成Swagger2
    springsecurity简单学习
    Java8的新特性
    HttpClient
    Filter的使用
    Spring拦截器和SpringAop实现
    运维工程师打怪升级进阶之路 V2.0
    欢迎加入微信交流群交流
    赞!7000 字学习笔记,一天搞定 MySQL
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11310843.html
Copyright © 2011-2022 走看看