new delete
\(new分配内存, delete释放new分配的内存.\)
new
\(在默认情况下,动态内存的对象是默认初始化的,所以内置类型或组合类型的对象的值是未定义的.\)
string *ps = new string; // 初始化位空的string
int *pi = new int // int的值未定义
\(动态分配内存初始化:直接初始化,构造方式,列表初始化\)
int *pi = new int(1024) // 直接初始化
string *ps = new string(10, '9') // 类的构造方法
vector<int> *pv = new vector<int> {0, 1, 2, 3, 4, 5} // 列表初始化
动态分配const对象
\(动态分配的const对象必须初始化.\\对于一个定义了默认构造函数的类,可以隐式初始化.\\其他类型的对象必须显示初始化.\\new返回指向指向const的指针.\)
const int *pci = new const int(1024); // 显式
const string *psc = new const string; // 隐式初始化一个空string
new和数组
\(new一个数组,要在类型后加[],在其中指明数目,返回指向第一个对象的指针.\)
int *p = new int[get_size()];
\(方括号内必须是整型但不需要是常量.\)
初始化动态分配对象的数组
\(默认下,new分配的对象,都是默认初始化的.\\也可以进行值初始化,后面加().\)
int *pia = new int[10]; // 10个未初始化int
int *pia2 = new int[10](); // 10个值初始化为0的int
string *psa = new string[10]; // 10个空string
string *psa2 = new string[10](); // 10个空string
\(也可以用初始化表:\)
int *pia3 = new int[5]{0, 1, 2, 3, 4};
string *psa3 = new string[10]{"a", "an", "the", string(3,'x')};
分配空数组是合法的
char arr[0]; // 错误:不能定义长度为0的数组
char *cp = new char[0]; // 正确:但cp不能解引用
\(当我们new一个空数组时,返回一个合法的非空指针.\\此指针保证与new返回的其他指针都不同,此指针像尾后迭代器.\)
delete
\(防止内存耗尽,用delete将动态内存归还给系统.\)
delete p; // p必须指向一个动态内存分配的对象或空指针
\(释放一块并非new分配的内存,或者将相同的指针释放多次,其行为是未定义的.\)
int i, *pil = & i, *pi2 = NULL;
double *pd = new double (33), *pd2 = pd;
delete pil // 未定义:pil指向局部变量
delete pd;
delete pd2 // 未定义:pd2所指内存已被释放过
delete pi2 // 正确:释放一个空指针总是没错的
\(虽然一个const对象的值不能被改变,但它本身是可以被销毁的.\)
const int *pci = new const int(1024);
delete pci; //释放一个const对象
动态对象的生存期直到被释放为止
\(对于通过内置指针类型来管理的内存(new出来的),直到被显示释放前都是存在的.\)
Foo *factory(T arg) {
// 返回指向动态内存的指针
return new Foo(arg); // 调用负责释放
}
void use_factory(T arg) {
Foo *p = factory(arg); // p离开了作用域,但指向的内存没有释放!
}
delete 之后重置指针值
\(当我们delete一个指针后,指针值就无效了.\\虽然无效了,但机器上指针仍然保留了(已释放)动态内存的地址.\\指针变成了空悬指针:曾经保留了数据对象但现在已无效的内存指针.\)
释放动态数组
delete p; // p必须指针一个动态分配对象或空
delete [] pa; // pa必须指向一个动态分配的数组或空
shared_ptr 和 new结合
\(可以用new返回的指针初始化智能指针.\)
shared_ptr<int> p2(new int(42));
\(接受指针参数的智能指针构造函数时explicit的.\\因此不能把内置指针隐式地转化成一个智能指针,必须使用直接初始化形式.\)
shared_ptr<int> p1 = new int(1024) // 错误: 必须使用直接初始化
shared_ptr<int> p2(new int(1024)) // 正确: 使用了直接初始化的方式
\(反过来,一个返回shared\_ptr的函数不能在其返回语句中隐式转换一个普通指针:\)
shared_ptr<int> clone(int p) {
return shared_ptr<int> (new int(p)); // 错误: 不是隐式转换
}