我的C++学习之路--02.构造函数和析构函数

来源:互联网 发布:2016淘宝开店费用 编辑:程序博客网 时间:2024/05/21 21:47
02.构造函数和析构函数
一、About 构造函数:
OK,先来看看构造函数。。。
作用:对对象本身做初始化工作,也就是给用户提供初始化类中成员变量的一种方式。
要点:
<1>.构造函数不能有返回值,函数名和类名相同
<2>.如果一个类中没有定义构造函数,那么C++编译器会在某些情况下为该类提供一个默认的构造函数。这个默认的构造函数是一个不带参数的构造函数。
<3>.创建一个对象时,系统会自动调用构造函数。

二、About 析构函数
作用:在一个对象的生命周期结束时,释放这个对象所占有的资源
要点:
<1>.析构函数没有参数和返回值,所以它也不能够重载
<2>.如果一个类中没有定义析构函数,系统会自动生成一个默认的析构函数,这个函数为空函数,什么都不做。
<3>.调用条件:a.在一个函数中定义一个对象,当函数调用结束的时候,系统会自动调用析构函数来删除在这个函数体内创建的对象,包括主函数。
 b.用new运算符动态构建的对象,在使用delete运算符释放它时。

三、对了  !还有拷贝构造函数:
 拷贝构造函数的格式为:类名(const 类名& 对象名);//拷贝构造函数的原型,参数是常量对象的引用。由于拷贝构造函数的目的是成员复制,不应修改原对象,所以建议使用const关键字。
构造函数实际上也是构造函数,具有一般构造函数的所有特性,其名字也和所属类名相同。拷贝构造函数只有一个参数,这个参数是对某个同类对象的引用。
在以下三种情况下被调用:
(1).用类的一个已知的对象去初始化该类的另一个对象时。(如:A=B 或 A(B));
(2).函数的形参是类的对象,调用函数进行形参和实参的结合时。(定义一个函数A,A函数的形参是类的对象,在另外一个函数B中调用这个函数A,实参将具体对象传给形参,这时会调用构造函数)
(3).函数的返回值是类的对象,函数执行完反悔调用者。(定义一个函数A,该函数的返回值是一个类的对象,在函数B中定义类的对象来接收A的返回,这个时候会调用拷贝构造函数)

四、再来看看深浅拷贝吧。。。
1.浅拷贝:所谓浅拷贝,指的是在对象复制时,只是对对象的数据成员进行简单的赋值,默认拷贝构造函数执行的是浅拷贝。在实际使用中,大多数的浅拷贝已经能很好的完成工作,但是一旦对象存在了动态成员,那么浅拷贝就会出错。

ege:
class A{

public : 
A()
{
p = new int(100);
}
~A()
{
if(p!= NULL)
delete p;
}

private:
int i,j;
int * p;
};
 
int main()
{
A a;
A b(a);
return 0;
}
【说明】:以上代码运行时会出现一个问题,原因在于进行对象复制的时候,对于动态分配的内容没有进行正确的操作。
【原因】:定义一个a对象后,由于在构造函数中有一个动态分配的语句,所以系统会在堆中为a对象分配一段内存区域。
在使用a赋值b时,由于执行的是浅拷贝,只是将成元的值进行赋值,所以此时a.p 和b.p具有相同的值,即这两个指针指向堆里的同一空间。
所以,在销毁对象的时候,两个对象的析构函数将会对同一内存空间释放两次,这样肯定会出错。
- - - - - - - - - -  - -因此我们需要使用深拷贝来解决这个问题- - - - - - - - - - - -
      
2.深拷贝
在深拷贝的情况下,对于对象中的动态成员,就不能仅仅简单的赋值啦,而应该重新分配空间。

现在对上面的出错代码进行改正:
class A{

public:

A()
{
p = new int(100);
}
A(const A &r)
{
i = a.i;
j = a.j;
p = new int;
*p = *(r.p);
}
~A()
{
if(p!=NULL)
delete p ;
}
private:
int i , j ;
int *p;
};

int main()
{
A a;
A b(a);
return 0;
}

这样,再次运行的时候,就不会出错了,因为a和b分别指向了空间大小相同的的两个存储空间,释放的时候就不会出现上述的同一片内存被释放两次的情况。

好了,今天就先到这吧,我坚信---知识是个积累的过程,加油!!
原创粉丝点击