new分配数组空间

来源:互联网 发布:lumantou最新域名 编辑:程序博客网 时间:2024/05/17 01:19
1.关于new 操作符:

new操作返回空间地址。delete运算符删除new创建的对象。

注意:new创建的对象必须有确定的空间大小,否则无法创建。如:

class C1
{
public:
C1();
int *p[];//warning C4200: nonstandard extension used : zero-sized array in struct/union
j};

class C2
{
public:
void increasecross();

CCross *p;
};
void C2::increasecross()
{
p=new C1[1]; //error C2233: '<Unknown>' : arrays of objects containing zero-size arrays are illegal
}

注意关于操作指针数组是,数组要有确定的量值。在Excerpt C Programming:*p[]表示一个指针的数组,而(*P)[]表示一个指向int数组的指针([]优先级高于*),*p[]没有定义数组大小,无法使用new来操作。

new有一点非常的重要:(摘自MSDN)
When new is used to allocate a multidimensional array of objects, it yields a pointer to the first element of the array, and the resultant type preserves the size of all but the leftmost array dimension. For example:

new float[10][25][10]

yields type float (*)[25][10]【这句话非常的重要,表:产生的类型是……】. Therefore, the following code will not work because it attempts to assign a pointer to an array of float with the dimensions [25][10] to a pointer to type float:

float *fp;
fp = new float[10][25][10];

//The correct expression is:

float (*cp)[25][10];//【这里同C 专家编程中的一样,表示cp是一个指向[25][10]类型的指针】
cp = new float[10][25][10];

//The definition of cp allocates a pointer to an array of type float with dimensions [25][10] — it does not allocate an array of pointers.

可见为类似 int (*p)[10];赋值可采用一下方法:
//
int x[10][10];//注意这里的x必须定义为一个二维变量才可以
p=x;
//
p=new int[10][10];

 

 

 

二维数组

如果二维数组大小要在运行的时候才能确定,只能开在堆区,在C++里面在堆区分配内存用的是运算符new,它返回它操作数类型的指针。但是它不能直接开两个维数都不确定的二维数组,下面介绍几种开二维数组的方法。另外在用完了数组后,一定要记得清理内存,在C++里用运算符delete,对于清理数组用delete[] ,如果忘了写最后几行代码,就是C++里最常见的内存泄露问题。

1.
    A (*ga)[n] = new A[m][n];
    ...
    delete []ga;
缺点:n必须是已知
优点:调用直观,连续储存,程序简洁(经过测试,析构函数能正确调用)
本人测试结果:在vc6.0下测试报错

2. A** ga = new A*[m];
    for(int i = 0; i < m; i++)
        ga[i] = new A[n];
    ...
    for(int i = 0; i < m; i++)
        delete []ga[i];
    delete []ga;
缺点:非连续储存,程序烦琐,ga为A**类型
优点:调用直观,n可以不是已知

本人测试结果:在vc6.0下测试运行ok

3. A* ga = new A[m*n];
    ...
    delete []ga;
缺点:调用不够直观
优点:连续储存,n可以不是已知

本人意见:此方法比较保险,用一维数组来表示二维数组,但是需要进行一维下标到二维下标的映射。

下面的方法主要运用了vector模板相关知识:

4. vector<vector<A> > ga;
    ga.resize(m);                       //这三行可用可不用
    for(int i = 1; i < n; i++)          //
        ga[i].resize(n);                //
    ...

缺点:非连续储存,调试不够方便,编译速度下降,程序膨胀(实际速度差别不大)
优点:调用直观,自动析构与释放内存,可以调用stl相关函数,动态增长

5. vector<A> ga;
    ga.resize(m*n);
方法3,4的结合


附:

2的改进版(Penrose提供,在此感谢)
    A** ga = new A*[m];
    ga[0] = new A[m*n];
    for(int i = 1; i < m; i++)
        ga[i] = ga[i-1]+n;
    ...
    delete [] ga[0];
    delete [] ga;
缺点:程序烦琐,ga为A**类型
优点:连续储存,调用直观,n可以不是已知

下面是一些错误和没成功的版本

1. A* ga = new A[m][n];
必然错误,前后的类型就不一致。

2. vector<A[n]> ga;
   ga.resize(m);

   gcc 3.2下编译失败,不知道其它编译器效果如何
   也不知道标准是否允许

函数参数也可以是二维及及更高维数组。但必须指定除最高维以后的各维大小。这一点和初始化时,可以省略不写最高维大小的规则一致:

//定义一个使用二维数组作为参数

void Func(int arr[][5]) //第二维的大小可以不指定

{

...

}

//定义一个使用三维数组作为参数

void Func(int arr[][2][5]) //第三维的大小可以不指定

{

...

}

原创粉丝点击