类的构造、拷贝、赋值、析构函数


  构造、拷贝、赋值、析构函数是类的四个特殊成员函数,其特殊之处在于,即使我们没有定义这些函数,编译器也会自动提供默认函数,但如果我们提供了这些函数的显式定义,那么编译器将不会再提供。这可能导致一些隐藏的问题,因此,我们需要对他们的实现进行充分的认识。

默认构造函数

  假定有一个类Klunk,那么其默认构造函数定义如下:

Klunk::Klunk(){}

  编译器为我们提供了一个不接受任何参数,也不执行任何操作的构造函数,我们可以像下面这样调用:

Klunk lunk;

  但是这种不做任何操作的构造函数也许并不是我们需要的,那么我们就可以显式定义默认构造函数,如下:

Klunk::Klunk()
{
	klunk_ct = 0;
}

复制构造函数

  复制构造函数用于将一个对象复制到新创建的对象中,它接收一个指向类对象的常量引用作为参数,形式如下:

String(const String& );

何时调用

  以下情形都会调用复制构造函数:

  • String ditto(motto);
  • String metoo = motto;
  • String also = String(motto);
  • String *pStr = new String(motto);
  • 函数值传递对象
  • 函数返回对象

  值得注意的是,即使我们调用赋值运算符,也会调用拷贝构造函数。

有何功能

  默认复制构造函数在复制过程中,会将成员的值进行逐个拷贝;如果成员中也有类成员存在,那么也将递归拷贝。但是需要注意的是,以上过程都是一种浅拷贝,这在碰到指针时将会带来灾难:创建了一个新的指针指向原指针指向的地址,而没有额外分配新的空间。这将导致:两个对象中都包含了指向同一地址的指针,在进行析构时,可能导致程序异常。
  因此,我们需要深拷贝,与浅拷贝不同,深拷贝在进行复制时将会额外为指针指向额外分配新的空间,然后再进行值拷贝。如下所示:

String :: String(const String& st)
{
...
	str = new char[len + 1];
	strcpy(str,st.str);
...	
}

赋值运算符

  赋值运算符接收一个指向类对象的常量引用作为参数,而返回一个指向类对象的引用。形式如下:

String & String::operator=(const String&);

  赋值运算符和复制拷贝类似,也是逐个拷贝,因此,也需要注意浅拷贝带来的问题。所以大多数时候需要我们实现自定义的复制运算符,在实现过程中,我们需要注意以下几个问题:

  • 由于目标对象可能引用了以前分配的数据,所以函数应当使用delete[]来释放这些数据;
  • 函数应当避免赋值给自身,否则,给对象重新赋值前,释放内存操作可能删除对象的内容。
  • 返回一个指向调用对象的引用。

析构函数

  析构函数,不必再作过多介绍,我们主要用它释放动态分配的内存。

总结

  综上所述,我们可以完成一个类的基本实现了,以自定义String类为例,代码如下:

class String
{
public:
    String(const char *str = NULL);
    String(const String &str);
    ~String(void);
    String &operator=(const String &str);

private:
    char *m_data;
};

String::String(const char *str)
{
    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 &str)
{
    int length = strlen(str.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, str.m_data);
}

String &String::operator=(const String &str)
{
    if (this == &str)
        return *this;

    if (m_data)
        delete[] m_data;

    int length = strlen(str.m_data);
    m_data = new char[length + 1];
    strcpy(m_data,str.m_data);
    return *this;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值