c++构造函数和析构函数

1.c++的构造函数有默认构造函数,一般的构造函数,赋值构造函数,拷贝构造函数(复制构造函数),强制类型转化构造函数。
2.如果没有定义构造函数和析构函数,则c++编译器会按照“位拷贝”的方式提供默认的构造函数(不初始化),默认的赋值构造函数(浅赋值),默认的拷贝构造函数(浅拷贝),默认的析构函数。位拷贝要小心指针,静态数据成员。
class String
{
public:
String(const char *str = NULL);
String(const String &other);
~String(void);
String & operator=(const String &other);
bool operator==(const String &str);
friend ostream & operator<<(ostream& o,const String &str);
private:
char *m_data;
};
3.例如如下的string类的两个对象stra和strb,stra =”windows”,strb = “linux”,如果没有进行深赋值,将strb赋值给stra即执行stra = strb,则stra.m_data和strb.m_data指向同一块内存区域,虽然stra.m_data的值变为linux,但这样会造成以下问题:
①stra.m_data原来指向的内存区域未被释放,会造成内存泄漏。
②stra.m_data和strb.m_data指向同一块内存区域,任何一方的改变都会影响另一方。
③当对象析构时strb.m_data所指向的区域会被释放两次(可能会造成悬挂指针)。
正确的拷贝构造函数书写如下:

String::String(const char *str)  
{  
    if (str == NULL){  
        m_data = new char[1];  
        *m_data='\0';  
    }else{  
        int len=strlen(str) + 1;  
        m_data = new char[len];  
        strcpy_s(m_data,len,str);  
    }  
}  
/*析构函数*/
String::~String(void)  
{  
    delete [] m_data;  
}  

String::String(const String &other)  
{  
    int len = strlen(other.m_data) + 1;  
    m_data = new char[len];  
    strcpy(m_data,len,other.m_data);  
}  
  /*赋值构造函数*/
String & String::operator=(const String &other)  
{  
   /*防止自赋值,自赋值可能导致m_data指向一个不存在的对象,可能会出现   间接的自赋值*/
    if (this == &other)  
        return *this;  
    /*防止内存泄漏*/
    delete []m_data;  
    int len = strlen(other.m_data) + 1;  
    m_data = new char[len];  
    strcpy_s(m_data,len,other.m_data);  
    /*返回的是对象,而不是对象的地址,因为引用只是对象的别名*/
    return *this;  
}  
 /*判断是否相等*/
bool String::operator==(const String &str)  
{  
    return strcmp(m_data,str.m_data) == 0;  
}  

ostream &String:: operator<<(ostream &o,const String &str)  
{  
    o<<str.m_data;  
    return o;  
}

4.拷贝构造函数的使用场景:
①对象以值传递的方式传入函数参数

void fun(String s){
}
fun(test);

test对象传入形参时,会产生一个临时变量,假设为s,然后调用拷贝构造函数把test拷贝给s,fun函数执行完后析构掉s.
②对象以值传递的方式从函数返回

string fun(){
string s("123");
return s;
}

执行过程:首先会产生一个临时变量就叫tmp,然后调用拷贝构造函数把s拷贝给tmp,然后fun程序结束后析构掉s,等到调用fun的函数结束后析构掉tmp.
③ 对象需要通过另外一个对象进行初始化;
string s(“123”);
string s1 = s;
string s2(s);
后两句都会调用拷贝构造函数。
通过声明一个私有拷贝构造函数,私有构造函数,私有赋值构造函数可以防止默认拷贝,默认构造,默认赋值构造发生。
5.拷贝构造函数形式
对于一个类X, 如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.类中可以存在超过一个拷贝构造函数,如果一个类中只存在一个参数为 X& 的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化.如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。这个默认的参数可能为 X::X(const X&)或 X::X(X&),由编译器根据上下文决定选择哪一个。
赋值运算符和复制构造函数都是用已存在的B对象来创建另一个对象A。不同之处在于:赋值运算符处理两个已有对象,即赋值前B应该是存在的;复制构造函数是生成一个全新的对象,即调用复制构造函数之前A不存在。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值