三种形式的new表达式
<1> 单个对象的动态分配
<2> 数组的动态分配
<3> 定位new表达式
------------------------------------------------------------------
<1>
#define TR(S) cout << #S" : " << S << endl
int *pi = new int(11); // initializer
TR(*pi);
int i = 22;
int *q = new int; //assign
*q = i;
TR(*q);
* 因为new表达式是从堆上申请内存,但堆上空闲储存区是有限的,但空闲储存区内存耗尽时,导致new表达式失败,抛出bad_alloc异常
* 常见new错误 <1> delete表达式失败(内存泄漏 memory leak) <2>对同以内存用2次delete <3>对象被释放后继续读写该对象
---------------------------------------------
auto_ptr (自动管理用new表达式动态分配的内存)
auto_ptr pi(new int(11));
cout << *pi << endl;
pi的作用域跟普通变量的作用域一样的,在pi的生命期结束时, 被释放
{
auto_ptr pi(new int(11));
}
cout << *pi << endl; // error C2065: 'pi' : undeclared identifier
------------------------------------------------------------------------
auto_ptr p1(new int(11));
auto_ptr p2(new int(22));
cout << *p1 << endl;
cout << *p2 << endl;
p1 = p2;
cout << *p1 << endl;
//cout << *p2 << endl; // error 这样p2被重置为0
if (p2.get() == 0) //
cout << "p2 is alive" << endl;
p2.reset(new int(33)); // 只能这样重置p2
cout << *p2 << endl;
----------------------------------------------------------------------
auto_ptr str1(new string("aaaaa"));
str1.reset(new string("bbbbbbbbb"));
cout << *str1 << endl;
str1->assign("ccccc"); //这样更有效...
cout << *str1 << endl;
需要包含头文件string 和memory 刚才一时情急忘了加#inlcude 然后居然把输出写成cout << str1 << endl;没有解引用...呵呵...- -!
* 用auto_ptr对象并不比直接使用指针代价高,大多操作都是inline的
*auto指针的是用指针的所有权方式,当把一个指针赋值给另一个指针的时候,后者拥有所有权,前者不再指向原来的对象,被赋值为0.
---------------------------------------------------------------------------
int *p = 0;
if ( !p )
cout << "p is non-initialize" << endl;
auto_ptr p2; // 从这里也能看出跟普通指针的不同, auto_ptr自动将对象初始化为0
if (!p2.get())
cout << "p2 is non-initialize" << endl;
*使用普通指针是可以用是否为0,而auto_ptr不可以,auto_ptr用get()返回对象内部的底层指针(用reset()来重置一个底层指针),
----------------------------------------------------------
* 不能用一个指向"内存不是用new分配的"指针来初始化或者赋值auto_ptr指针
* 不能让两个auto_ptr对象拥有空闲存储区内同一对象的所有权()
2>数组的动态分配
int *pi = new int[11]; // 分配有11个元素的动态数组
int (*pia)[11] = new int [22][11]; //分配一个含有 22 * 11 个元素的二维数组
* 动态分配的数组不能给出初始化值,一般在 for 循环中一个一个的初始化
eg: for(int i = 0; i < 11; i++)
pi[i] = 0;
* 动态数组的第一维不必是常量值, 这样就不必在编译时刻就知道维数,我们可以根据需要分配大小合适的内存单元
* 释放动态数组: delete [ ] pi; 如果不小心忘记了空括号,编译器不会捕捉到这个错误, 务必要小心
* 一般为了避免动态分配数组带来的内存管理的问题, 我们使用c++ 的 标准库vector, list or string 会自动管理内存的容器类型
---------------------
常量对象的动态分配
const int *pic = new const int(1024);
* const 对象必须被初始化, 否则会编译错误,(因此我们也不能创建const数组,因为const数组不能被初始化,除了类数组)
* 用new表达式返回的值作为初始值的指针必须是一个指向const类型的指针. eg: const int
* 它的生命期同样也用delete表达式来结束 eg: delete pic;
=============================================================
<3>定位new表达式(placement new expression)
形式: new (place_address) type-specifier
头文件: #include
place_adress必须是指针
eg:
int *buf = new int[2];
int *pb = new (buf) int;
*pb = 11;
cout << *pb << endl; // 11
cout << *buf << endl; // 11
cout << pb << endl; // 同样pb跟buf的所指向的地址也是相同的
cout << buf << endl; //
int *pp = new (buf + 1) int;
*pp = 22;
* 因为定位符并不分配内存,所以我们并没有与定位符相匹配的delete表达式, 对此我们需要删除的是分配内存的指针,在上面的例子中我们 delete [] buf;