1、在C++中,一般都用new/delete来申请和释放内存,对于以下几种new的用法,各自的区别是什么呢?
int *p1 = new int; int *p2 = new int(); int *p3 = nre int(1); // define class A; A *p4 = new A; A *p5 = new A(); A *p6 = new A[10]; A *p7 = new A[10]();
根据<C++ primer 第四版>5.11节中关于new的描述,new A属于Default Initializing of Dynamically Allocated Objects(动态创建对象的默认初始化),而new A()则属于Value Initalizing of Dynamically Allocated(动态创建对象的值初始化)。
new A | new A() | new A(parameters) | |
A为内置类型 | 无初始化操作 | 进行值初始化,例A为int类型,则初始化为0 | 进行值初始化,A被初始化为parameters |
A为class/struct | 调用默认构造函数,A中的成员是否初始化依赖于构造函数的实现 | 若自定义了默认构造函数,则调用自定义的默认构造函数,否则调用系统默认构造函数,并对A中的成员进行值初始化 | 调用A的自定义构造函数 |
因此上面的代码的执行结果分别为:
- p1 指向了一个未被初始化的int空间
- p2 指向了一个被初始化的空间,其值为0
- p3 指向了一个被初始化的int空间,其值为1
- p4 指向了一个调用默认构造函数的实例A,除非A的默认构造函数对A进行初始化,否则A的成员全为未初始化变量
- p5 指向了一个条用了默认构造函数的实例A,若A自定义了默认构造函数,A成员变量的初始化依赖于自定义的默认构造函数,反之A的成员变量全为初始化后的变量
- p6 p7指向了调用默认构造函数的实例A的数组,其执行结构同p4 p5相同。
2、C++ 中new一个数组,释放的时候的写法注意。
class A { public: int a; }; int main() { A *p = new A[10]; // p 指向一个拥有10个A实例的地址 delete p; // 释放一次 delete []p; // 释放10次 return 0; }
new []返回的地址会后移4个字节,并用那4个存放数组的大小!而new不用后移这四个字节
delete[]根据那个4个字节的值,调用指定次数的析构函数 ,同样delete也不需要那四个字节
再回到《高质量C++编程指南》:
delete []objects; // 正确的用法
delete objects; // 错误的用法
后者相当于delete objects[0],漏掉了另外99 个对象
delete []objects; // 正确的用法
delete objects; // 错误的用法
后者相当于delete objects[0],漏掉了另外99 个对象
严格应该这样说:后者相当于仅调用了objects[0]的析构函数,漏掉了调用另外99 个对象的析构函数,并且在调用之后释放内存时导致异常(如果存在析构函数的话),如果对象无析构函数该语句与delete []objects相同