C++的构造函数

110 阅读3分钟

构造函数主要有以下几种

  • 默认构造函数

    不带任何参数,可以自己显式定义,也可以由C++隐式定义

  • 一般构造函数

    也称重载构造函数,可以有各种参数形式,一个类可以有多个一般构造函数

  • 转换构造函数

    只有一个参数,根据参数类型的对象创建一个该类对象

  • 拷贝构造函数

    用一个已存在的类对象A去构造一个不存在的类对象B,会调用拷贝构造函数,参数是一个左值对象;在对象被拷贝后临时对象和拷贝构造的对象各自占有不同的堆内存,就是一个副本。从下图中可以看到,临时对象和新建对象a申请的堆内存同时存在。

image.png

  • 移动构造函数

    参数是一个右值对象,让临时对象控制的内存的空间转移给构造出来的对象,这样就相当于把它移动过去了。从下图中可以看到,原本由临时对象申请的堆内存,由新建对象a接管,临时对象不再指向该堆内存。

image.png

  • 拷贝赋值函数

    用一个已存在的类对象A赋值给一个已存在的类对象B,会调用拷贝赋值函数

  • 移动赋值函数

    类似于移动构造函数,新对象直接接管原内存,避免了内存的一次拷贝

class Sample_C {
public:
    //默认构造函数
    Sample_C() {
        m_k = 0;
        m_f = NULL;
    }
    
    //一般构造函数
    Sample_C(int p_k, float* p_f) {
        m_k = p_k;
        m_f = p_f;
    }
    
    //转换构造函数
    Sample_C(int p_k) {
        m_k = p_k;
        m_f = NULL;
    }
    
    //拷贝构造函数
    Sample_C(const Sample_C& p_sample) {
        m_k = p_sample.m_k;
        m_f = new float[m_k];
        memcpy(m_f, p_sample.m_f, m_k*sizeof(float));
    }
    
    //移动构造函数
    Sample_C(const Sample_C&& p_sample) {
        m_k = p_sample.m_k;
        m_f = p_sample.m_f;
    }
    
    //拷贝赋值函数
    Sample_C& operator=(const Sample_C& p_sample) {
        m_k = p_sample.m_k;
        m_f = new float[m_k];
        memcpy(m_f, p_sample.m_f, m_k*sizeof(float));
    }
    
    //移动赋值函数
    Sample_C& operator=(const Sample_C&& p_sample) {
        m_k = p_sample.m_k;
        m_f = p_sample.m_f;
    }
    
    void alloc(int p_k) {
        m_k = p_k;
        m_f = new float [m_k];
        for (int i = 0; i < m_k; i++) {
            m_f[i] = 2.0 + i;
        }
    }
private:
    int m_k;
    float* m_f;
};

int main() {
    //默认构造函数
    Sample_C A;
    A.alloc(2);
    
    //拷贝构造函数
    Sample_C B(A);
    
    //移动构造函数
    Sample_C C(std::move(A));
    
    Sample_C D;
    //拷贝赋值函数
    D = A;
    
    Sample_C E;
    //移动赋值函数
    E = std::move(A);
    
    return 0;
}

深拷贝和浅拷贝

需要新开辟内存空间的叫深拷贝,不需要开辟内存空间,将对象的成员值直接赋值的叫浅拷贝

//深拷贝
Sample_C(const Sample_C& p_sample) {
    m_k = p_sample.m_k;
    m_f = new float[m_k];
    memcpy(m_f, p_sample.m_f, m_k*sizeof(float));
}

//浅拷贝
Sample_C(const Sample_C& p_sample) {
    m_k = p_sample.m_k;
    m_f = p_sample.m_f;
}

当成员变量中有指针的时候,使用浅拷贝会导致多个指针指向同一块内存空间,在析构的时候会出现指针悬挂的问题。

参考文章 :blog.csdn.net/weixin_4478…