形参与实参
形参:是函数声明时的参数,只说明参数名和类型,不是实际的参数,不能真正使用。
实参:运行时传给函数的参数,是实际的变量,形参在这时真正地被分配空间,并且赋值了实参的值。
一个函数的实参在内存中有自己固定的内存,直到函数执行结束才释放内存。而形参没有固定的内存,只在调用函数的时候有一个虚拟内存,等调用完毕就不再有内存。他们的关系是函数调用的时候,实参把值传给形参
构造函数
(1)构造函数不能有返回值,函数名为类名
(2)缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为0或者空。缺省构造函数是不带参数的
(3)创建一个对象时,系统自动调用构造函数
析构函数
析构函数没有参数和返回值。不能重载,一个类中只能定义一个析构函数,如果一个类中没有定义析构函数,系统会自动生成一个默认的析构函数,为空函数,什么都不做。调用条件:
(1)在函数体内定义的对象,当函数执行结束时,该对象所在类的析构函数会被自动调用。(在一个函数中定义一个对象,当函数调用结束,则会自动调用析构函数来删除在这个函数体内创建的对象,包括主函数。)
(2)用new运算符动态构造的对象,在使用delete运算符释放它时。
拷贝构造函数
拷贝构造函数实际上也是构造函数,具有一般构造函数的所有特性,其名字也与所属类名相同。拷贝构造函数中只有一个参数,这个参数是对某个同类对象的引用。
(1)用类的一个已知对象去初始化该类的另一个对象时。(初始化时A = B,也可以用A(B))
(2)函数的形参是类的对象,调用函数进行形参和实参的结合时。(定义一个函数A,A函数的形参是类的对象,在另外一个函数B中调用这个函数A,实参将具体的对象传递给形参,这时候会调用拷贝构造函数。)
(3)函数的返回值是类的对象,函数执行完返回调用者。(定义一个函数A,该函数的返回值是一个类的对象,在函数B中定义类的对象来接受函数A的返回,这时会调用拷贝构造函数。)
浅拷贝
所谓浅拷贝是指在对象复制时,只是对对象中的数据成员进行简单的赋值,这就是浅拷贝,默认的拷贝构造函数执行的也是浅拷贝。大多数情况之下“浅拷贝”能很好的工作,但是一旦对象存在了动态成员,那么浅拷贝就会出问题。
1、浅拷贝的应用
(1)拷贝构造函数
class A
{
char *p;
int len;
};
A obj2 = obj1;//调用obj2的拷贝构造函数Class(Class &other)
如果没有定义拷贝构造函数,就会调用C++自带的拷贝构造函数,此时:obj1的成员变量p和len都在栈区,p指针存放的是地址信息,指向堆中的数据(全局变量区复制过来的,注意:全局变量区和堆区都有这部分数据)。而C++自带的拷贝构造函数,执行了浅拷贝,只是在栈区把p和len复制了一份给obj2,故p也指向堆中的数据区域。在两个变量生命周期结束,需要析构时,obj2正常析构,数据析构,指针为NULL,obj1中的p就成了野指针。
(2)等号操作符
A obj1("A1");
A obj2("A2");
obj2 = obj1;//如果不自己重载operator = (),则调用C++自己的=操作符进行p和len的简单值拷贝,指针所指的堆中区域没有拷贝,obj1和obj2中的指针p指向堆中相同区域的数据。
深拷贝
在“深拷贝”下,对于对象中动态成员,就不能仅仅简单的赋值了,而是应该重新动态分配空间。
总结:
拷贝构造函数分为深拷贝和浅拷贝,一般情况之下浅拷贝已经满足要求,但是当存在动态成员时,浅拷贝就不能满足需求了。比如一个对象中有指针成员,只是通过简单的浅拷贝,只能让复制的对象指向同一片区域,而不是创建一片同样大小的区域,这就需要通过深拷贝来解决。
参考:http://blog.csdn.net/bluescorpio/article/details/4322682