复制构造函数 与 赋值函数 的区别

转自:http://www.cnblogs.com/kaituorensheng/p/3245522.html

构造函数、析构函数、赋值函数是每个类最基本的的函数。每个类只有一个析构函数和一个赋值函数。但是有很多构造函数(一个为复制构造函数,其他为普通构造函数。对于一个类A,如果不编写上述四个函数,c++编译器将自动为A产生四个默认的函数,即:

  • A(void)                                    //默认无参数构造函数
  • A(const A &a)                         //默认复制构造函数
  • ~A(void);                                //默认的析构函数
  • A & operator = (const A &a); //默认的赋值函数

既然能自动生成函数,为什么还需要自定义?原因之一是“默认的复制构造函数”和"默认的赋值函数“均采用”位拷贝“而非”值拷贝“

位拷贝  v.s.  值拷贝

为便于说明,以自定义String类为例,先定义类,而不去实现。

复制代码
#include <iostream>
using namespace std;

class String  
{
    public:
        String(void);
        String(const String &other);
        ~String(void);
        String & operator =(const String &other);
    private:
 
char *m_data;
int val; };
复制代码

位拷贝拷贝的是地址,而值拷贝拷贝的是内容。

如果定义两个String对象a, b。当利用位拷贝时,a=b,其中的a.val=b.val;但是a.m_data=b.m_data就错了:a.m_data和b.m_data指向同一个区域。这样出现问题:

  • a.m_data原来的内存区域未释放,造成内存泄露
  • a.m_data和b.m_data指向同一块区域,任何一方改变,会影响到另一方
  • 当对象释放时,b.m_data会释放掉两次

因此

当类中还有指针变量时,复制构造函数和赋值函数就隐含了错误。此时需要自己定义。

结论

  • 有一种特别常见的情况需要自己定义复制控制函数:类具有指针哈函数。
  • 赋值操作符和复制构造函数可以看成一个单元,当需要其中一个时,我们几乎也肯定需要另一个
  • 三法则:如果类需要析构函数,则它也需要赋值操作符和复制构造函数

注意

  • 如果定义复制构造函数(别的不管),编译器会自动生成默认复制构造函数
  • 如果定义了其他构造函数(包括复制构造函数),编译器不会生成默认构造函数
  • 即使自己写了析构函数,编译器也会自动生成默认析构函数

因此此时如果写String s是错误的,因为定义了其他构造函数,就不会自动生成无参默认构造函数。

复制构造函数  v.s.  赋值函数

复制代码
#include <iostream>
#include <cstring>
using namespace std;

class String  
{
    public:
        String(const char *str);
        String(const String &other);
        String & operator=(const String &other);
        ~String(void); 
    private:
        char *m_data;
};

String::String(const char *str)
{
    cout << "自定义构造函数" << endl;
    if (str == NULL)
    {
        m_data = new char[1];
        *m_data = '\0';
    }
    else
    {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

String::String(const String &other)
{
    cout << "自定义拷贝构造函数" << endl;
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
}

String & String::operator=(const String &other)
{
    cout << "自定义赋值函数" << endl; 

    if (this == &other)
    {
        return *this;
    }
    else
    {
        delete [] m_data;
        int length = strlen(other.m_data);
        m_data = new char[length + 1];
        strcpy(m_data, other.m_data);
        return *this;
    }
}

String::~String(void)
{
    cout << "自定义析构函数" << endl; 
    delete [] m_data;
}
int main()
{
    cout << "a(\"abc\")" << endl;
    String a("abc");

    cout << "b(\"cde\")" << endl;
    String b("cde");
    
    cout << " d = a" << endl;
    String d = a;

    cout << "c(b)" << endl;
    String c(b);

    cout << "c = a" << endl;
    c = a;

    cout << endl;
}

复制代码

执行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值