C++编译器构造类的潜规则

来源:互联网 发布:php怎么调用存储过程 编辑:程序博客网 时间:2024/06/05 12:14

C++在设计类的时候,没有显式定义构造函数和析构函数时,C++编译器会自动提供一下特殊成员函数:
1.默认构造函数
2.默认析构函数
3.复制构造函数
4.赋值运算符重载
5.地址运算符重载

他们的特性如下:
1.C++编译器提供的默认构造函数没有形参、函数体内也没有任何可执行的代码,只是提供了一个空壳,供程序编译通过。

2.C++编译器提供的默认析构函数同样没有形参、函数体内也没有任何实际可执行的代码。

3.默认复制构造函数:默认复制构造函数会将已有对象中的成员数据逐个复制到被初始化的对象中,但是static成员不会被做这样的操作,其实深入到内存中思考,static成员本质上并不是类中的成员。
假设实现了一个Test类,并且已经定义了一个Test t对象,则以下几种初始化对象的方式会调用复制构造函数:Test t1(t); Test t2 = t; Test t3 = Test(t); Test *t4 = new Test(t);
默认复制构造函数引发的问题:如果一个成员为指针变量,并且这个指针变量初始化对象调用构造函数时动态地申请了堆内存空间,显然,当对象的作用域结束之后,需要在析构函数中释放这段空间保证内存不会泄露;由于默认复制构造函数将对象中的成员挨个复制赋值,导致用存在的对象给新开辟的对象初始化时,他们会得到同样的一段堆内存空间,并且这段堆内存空间会在这两个对象的作用于结束之后被释放两次,这会给程序带来灾难性的麻烦。

4.赋值运算符:当使用已有的对象给另一个同类型的对象赋值时,在没有重载=运算符的情况下,C++编译器会默认为这种代码提供一个赋值操作,即将已有对象的成员挨个赋值给被赋值对象的成员。需要注意的是,在初始化对象的时候这么做并不一定是赋值运算符操作,这需要取决于编译器的实现,老式的C++编译器在编译下述代码:Test t1 = 6的时候,会先创建一个临时的Test对象,并用int型数据6初始化这个对象,然后再调用复制构造函数将这个临时对象的成员挨个复制给调用对象。

5.取地址运算符重载类比于ANSI C结构的取地址操作。