动态分配的对象被分配在程序的空闲存储区free store 的可用内存池中。C++中一般用new来申请内存,delete来撤消new申请的内存。
new有三种形式:
1、支持单个对象动态分配
例如:
int *p;
p = new int;
支持的类型有内置类型:int, double, char ....
还有自定义的类、结构体等等。
new成功后可直接初始化,如:
double *p;
p = new double(3.1415);
且结果返回的是一个指针,最后要用delete撤消。
此外,C++标准库提供了auto_ptr类模板,它可以帮助程序员自动管理用new 表达式动态分
配的单个对象(不幸的是,对用new 表达式分配的数组管理没有类似的支持,我们不能用auto_ptr 存储数组。如果这样做了结果将是未定义的)。
auto_ptr 对象被初始化为指向由new 表达式创建的动态分配对象。当auto_ptr 对象的生命期结束时,动态分配的对象被自动释放。也就是说不用delete来释放new申请的内存。
auto_ptr类模板在memoy中,使用时要加进来。auto_ptr定义有以下三种形式:
auto_ptr< type_pointed_to> identifier( ptr_allocated_by_new);
auto_ptr< type_pointed_to> identifier( auto_ptr_of_same_type);
auto_ptr< type_pointed_to> identifier
type_pointed_to 代表由new 表达式创建的对象的类型
identifier 变量名
ptr_allocated_by_new 初始值,而且要是new出来
auto_ptr_of_same_type 同种类型的另一对象
auto_ptr相关的一些操作:
1)、赋值,如
auto_ptr<int> ptr (new int (100) );
auto_ptr<int> ptr2(new int(200) );
ptr = ptr2;
在赋值之前由ptr 指向的对象被删除。赋值之后ptr 拥有int 型对象的所有权,该对象值为200, ptr2 不再被用来指向该对象。
2)、get()操作,返回auto_ptr对象内部的底层指针。
3)、reset()操作,设置auto_ptr对象底层指针。如:
auto_ptr <int> p;
if (p.get() != 0 && *p != 100)
*p = 100;
else
p.reset( new int (100) );
最后,使用auto_ptr类要注意的两点:
<1> 我们必须小心,不能用一个指向“内存不是通过应用new 表达式分配的”指针来初始化或赋值auto_ptr 。如果这样做了,delete 表达式会被应用在不是动态分配的指针上,这将导致未定义的程序行为。
<2> 我们必须小心,不能让两个auto_ptr 对象拥有空闲存储区内同一对象的所有权。一种很显然犯这种错误的方法是,用同一个指针初始化或赋值两个auto_ptr 对象。另一种途径是通过使用get()操作。例如
auto_ptr< string >
pstr_auto( new string( "Brontosaurus" ) );
// 喔! 现在两个指针都指向同一个对象
// 并都拥有该对象的所有权
auto_ptr< string > pstr_auto2( pstr_auto.get() );
release()操作允许将一个auto_ptr 对象的底层对象初始化或赋位给第二个对象,而不会使两个auto_ptr 对象同时拥有同一对象的所有权。release()不仅像get()操作一样返回底层对象的地址,而且还释放这对象的所有权。前面代码段可被正确改写如下
// ok: 两个对象仍然指向同一个对象
// 但是, pstr_auto 不再拥有拥有权
auto_ptr< string >
pstr_auto2( pstr_auto.release() );
2、支持数组动态分配
第一维可以是表达式、变量、常量,但不能为空,第二、三……维一定要是常量。如:
int *p = new int[1024];
int (*pp)[1024] = new int [2*3+1][1024];
3、定位new表达式(placement new expresssion)
定位new 表达式(placement new expression),可以允许程序员要求将对象创建在已经被分配好的内存中。使用时要包含头文件<new>。形式如下:
new (place_address) type -specifier
place_address 必须是个指针。如:
#include <iostream>
#include <new>
const int chunk = 16;
class Foo
{
public:
int val() { return _val; }
Foo() { _val = 0; }
private:
int _val;
};
// 预分配内存但没有Foo 对象
char *buf = new char[ sizeof(Foo) * chunk ];
int main()
{
// 在buf 中创建一个Foo 对象
Foo *pb = new (buf) Foo;
// 检查一个对象是否被放在buf 中
if ( pb->val() == 0 )
cout << "new expression worked!" << endl;
// 到这里不能再使用 pb
delete[] buf;
return 0;
}
编译并执行该程序产生下列输出
new expression worked
最后,说下常量对象的动态分配。
在空闲存储区创建的const 对象有一些特殊的属性。首先,const 对象必须被初始化;第二,用 new 表达式返回的值作为初始值的指针必须是一个指向const 类型的指针。如:
const int *p = new const int ( 100);
.
.
.
delete p;