VC中的new用法,菜鸟小结

今天菜鸟又出了个丑VC中的new用法,菜鸟小结 - 忆尤的大地 - 忆尤的大地,很简单的两指针数组数据加减乘除存入第三数组,就一直出现“unhandled exception in **.exe”要莫就是“Debug Error”,莫名奇妙,开始以为是new函数用错了,或者是因为开辟空间大小的问题,后来,百度说可能是数据类型强制转换导致最终释放空间不统一,但是试过了各种解决办法,没有效果。中午吃饭时候,给哥哥看了一眼,没想到,他一下子就看出了问题,大敲我脑袋VC中的new用法,菜鸟小结 - 忆尤的大地 - 忆尤的大地:“new float(1000)是什么东西?应该是中括号……”

      开始还不信,这……也太诡异了吧,然后-调试-没问题了……VC中的new用法,菜鸟小结 - 忆尤的大地 - 忆尤的大地

      在此总结new的用法:(摘自http://www.cppblog.com/rosinahua/archive/2007/04/03/21183.aspx)

     new有三种使用方式:plain new,nothrow new和placement new。
(1)plain new顾名思义就是普通的new,就是我们惯常使用的new。在C++中是这样定义的:
    void* operator new(std::size_t) throw(std::bad_alloc);
    void operator delete(void *) throw();
提示:plain new在分配失败的情况下,抛出异常std::bad_alloc而不是返回NULL,因此通过判断返回值是否为NULL是徒劳的。
(2)nothrow new是不抛出异常的运算符new的形式。nothrow new在失败时,返回NULL。定义如下:
    void * operator new(std::size_t,const std::nothrow_t&) throw();
    void operator delete(void*) throw();
(3)placement new意即“放置”,这种new允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数。定义如下:
    void* operator new(size_t,void*);
    void operator delete(void*,void*);
提示1:palcement new的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。
提示2:placement new构造起来的对象或其数组,要显示的调用他们的析构函数来销毁,千万不要使用delete。
char* p = new(nothrow) char[100];
long *q1 = new(p) long(100);
int *q2 = new(p) int[100/sizeof(int)];

一般用法,new的格式

构造函数。如果构造函数没有参数,则可以省略圆括号。

arguments

可选项。任意传递给新对象构造函数的参数。

说明

new 运算符执行下面的任务:

  • 创建一个没有成员的对象。
  • 为那个对象调用构造函数,传递一个指针给新创建的对象作为 this 指针。
  • 然后构造函数根据传递给它的参数初始化该对象。

示例

下面这些是有效的 new 运算符的用法例子。

my_object = new Object;my_array = new Array();my_date = new Date("Jan 5 1996");

 

二维数组new小结

转自水木清华

1.

    A (*ga)[n] = new A[m][n];

    ...

    delete []ga;

缺点:n必须是已知

优点:调用直观,连续储存,程序简洁(经过测试,析构函数能正确调用)

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可以不是已知

3.  A* ga = new A[m*n];

    ...

    delete []ga;

缺点:调用不够直观

优点:连续储存,n可以不是已知

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的结合

6. 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,2,3,6还有对应的malloc-free版本

个人推荐1和4,2可以用4来代替,3,5调用太烦琐,毕竟源程序是拿来看的

不是拿来运行的

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

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])  //第三维的大小可以不指定

{

  ...

}

你可能感兴趣的:(C++,内存,指针)