C++> delete关键字初探
delete有2个作用:
- 释放new分配的动态内存;
- 阻止编译器自动合成函数;
释放new分配的动态内存
delete需要与new配对使用,其参数可以是指向一块内存首地址或空指针(nullptr)。不能对同一块内存多次delete,但是可以对空指针多次delete。
注意delete和delete[] 的区别:
- delete p 释放p指向的(单个)内存,可用于释放单个内存对象;
- delete []p 释放p指向的内存区块,可用于释放一组内存(数组);
示例:
// 释放基本类型内存
int *pi = new int(20);
delete pi;
// 释放类对象内存
int *ps = new string("hello");
delete ps; // 会调用string类析构函数
// 释放数组类型内存
int *pa = new int[10];
delete []pa;
阻止编译器合成函数
适用于C++11以上版本。
如果没有为类编写构造函数、析构函数、拷贝构造函数、拷贝赋值运算符,以及移动拷贝函数、移动赋值运算符,编译器可能会为类合成默认的函数版本。显式使用delete,可以阻止编译器合成对应函数。
示例:
class MyObj {
public:
MyObj() = delete; // 阻止编译器合成构造函数,会导致类无法实例化
MyObj& MyObj(const MyObj &) = delete; // 阻止编译器合成拷贝构造函数,会导致类无法拷贝构造,如std::cin, std::cout
MyObj& operator=(const MyObj &) = delete; // 阻止合成赋值运算符,会导致类无法拷贝,如cin, cout, cerr
...
}
与delete对应的是default,default显式告诉编译器使用编译器自动合成的函数。
合成的默认构造函数,只有基类子对象和类类型对象会被初始化,而其他所有的非静态成员(如整数,指针,数组等),都不会初始化,对他们进行初始化的应该是程序员,而非编译器。
如果类包含了需要动态创建对象的指针,就不能依靠合成的构造函数、拷贝构造函数、拷贝赋值运算符。
参见C++关于编译器合成的默认构造函数
示例:
class MyObj {
public:
MyObj() = default; // 告诉编译器合成构造函数,作为默认构造函数,类的设计者不会实现该函数
MyObj& MyObj(const MyObj &) = default; // 告诉编译器合成拷贝构造函数,作为默认拷贝构造函数
MyObj& operator=(const MyObj &) = default; // 告诉编译器合成赋值运算符
...
}