免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 11814 | 回复: 14

关于operator new和operator new[]的区别 [复制链接]

论坛徽章:
0
发表于 2011-01-30 21:25 |显示全部楼层
如题,new和new[]的区别比较明显了,主要是new[]会多次调用构造函数,依次初始化对象。

但operator new和operator new[]不都是单纯的返回一个指向heap的void*指针么?有什么区别呢?请大家指教,谢谢!

论坛徽章:
0
发表于 2011-01-31 04:26 |显示全部楼层
ISO C++03 5.3.4
10 A new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array. For arrays of char and
unsigned char, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the most stringent alignment requirement (3.9) of any object type whose size is no greater than the size of the array being created. [Note: Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type, this
constraint on array allocation overhead permits the common idiom of allocating character arrays into which
objects of other types will later be placed. ]

12 [Example:
— new T results in a call of operator new(sizeof(T)),
— new(2,f) T results in a call of operator new(sizeof(T),2,f),
— new T[5] results in a call of operator new[](sizeof(T)*5+x), and
— new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).
Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions. The amount of overhead may vary from one invocation of new to another. ]

论坛徽章:
0
发表于 2011-01-31 10:28 |显示全部楼层
new 用于单个对象或实例的创建,就是调用类的构造函数。
   new []用于创建对象或实例的数组实例,并且地址是连续的。(内存分配的时候有可能不连续,但地址链表是连续的。)

论坛徽章:
0
发表于 2011-01-31 12:53 |显示全部楼层
感谢楼上两位,但两位说的还是new和new[]的区别而不是operator new和operator new[]的区别,按理说operator new和operator new[]都应该是单纯返回一个void *型指针,不应该有什么区别吧.

从二楼帖的ISO标准来看,new[]在调用operator new[]会传递一个比需要对象大的参数,而且这个增加量要求是对象中最大对齐要求的整数倍,这样在对operator new[]返回的已对齐指针进行offset后,仍然能够满足对齐要求,符合通常的语义.这个增加量应该是给delete []用来识别对象大小和数量以便多次析构对象用的.

但这些活都是new[]做的,operator new[]只是单纯的按要求返回了堆中内存的指针,这个动作和operator new没什么区别吧?

论坛徽章:
0
发表于 2011-01-31 12:55 |显示全部楼层
ISO C++03 5.3.4
10 A new-expression passes the amount of space requested to the allocation function ...
幻の上帝 发表于 2011-01-31 04:26



    请教一下ISO标准哪里去找,谢谢!

论坛徽章:
0
发表于 2011-01-31 13:53 |显示全部楼层
本帖最后由 liwangli1983 于 2011-01-31 13:54 编辑

  1. #include<iostream>
  2. #include<cstdlib>
  3. using std::cout;
  4. using std::endl;
  5. using std::hex;
  6. class X
  7. {
  8.         public:
  9.                 X(int q = 0): a(q) {}
  10.                 ~X() { cout << "del" << endl; }
  11.         private:
  12.                 int a;
  13. };

  14. void *operator new[](size_t size)
  15. {
  16.         void *p = malloc(size);
  17.         cout << "new[]:" << size << endl;
  18.         cout << "new[]:" << hex << p << endl;
  19.         return p;
  20. }

  21. int main(void)
  22. {
  23.         X *q = new X[5];
  24.         cout << hex << q << endl;
  25.         cout << *(reinterpret_cast<int *>(q) - 1) << endl;
  26.         delete [] q;
  27.         q = new X(3);
  28.         cout << hex << q << endl;
  29.         delete q;

  30.         return 0;
  31. }
复制代码
输出结果是:
  1. abc@dlstd:~/cpptest/test_new$ ./a.out
  2. new[]:24
  3. new[]:0x804a008
  4. 0x804a00c
  5. 5
  6. del
  7. del
  8. del
  9. del
  10. del
  11. 0x804a028
  12. del
复制代码
从测试程序来看,当需要调用析构函数的时候(之前实验new一个int数组,结果传递给operator new[]的size整好是所需要的20),传递给operator new[]的参数值是24,而实际上只需要20.从malloc返回的地址和new返回的地址来看,正好差了4,再从reinterpret_cast后打印的数值来看,多占用的四字节是以int型保存的数值5,正好是数组的元素个数.
从后一个new单个对象来看,重载operator new[]没有影响到operator new.

还是不明白特意区分两者的原因.

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
发表于 2011-01-31 14:42 |显示全部楼层
本帖最后由 w_anthony 于 2011-01-31 14:45 编辑
输出结果是:从测试程序来看,当需要调用析构函数的时候(之前实验new一个int数组,结果传递给operator new[]的 ...
liwangli1983 发表于 2011-01-31 13:53



    operator new[]返回的地址偏移4个字节,对于直接或者间接存在析构函数的类才有意义,这样在delete[]时刻程序才知道要按顺序调用几次析构函数,如果这个类没有析构函数,那么部分编译器甚至不会做这4个字节的偏移,这种情况下delete[]和delete是相同的(不过当然也不能依赖编译器的这个行为,当用delete[]还是得用它)。

论坛徽章:
0
发表于 2011-01-31 15:20 |显示全部楼层
operator new[]返回的地址偏移4个字节,对于直接或者间接存在析构函数的类才有意义,这样在delet ...
w_anthony 发表于 2011-01-31 14:42



    多还是少那几个字节,完全是由new[]决定的.operator new[]仅仅是按照new[]传过来的值分配相应大小的内存而已,从行为上来看operator new[]和operator new根本没有区别啊.当然如果用户重载后就另当别论了.

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
发表于 2011-01-31 15:53 |显示全部楼层
多还是少那几个字节,完全是由new[]决定的.operator new[]仅仅是按照new[]传过来的值分配相应大小 ...
liwangli1983 发表于 2011-01-31 15:20



    呃,你只是想问为什么重载operator new[]和operator new不设计成一个东西吗?确实没什么人只去重载其中的一个,留下另外一个不去重载。或许只是当初刚好设计这样了吧。

论坛徽章:
0
发表于 2011-01-31 16:53 |显示全部楼层
呃,你只是想问为什么重载operator new[]和operator new不设计成一个东西吗?确实没什么人只去重 ...
w_anthony 发表于 2011-01-31 15:53



    这么说来两者行为其实没有区别,只是由不的new操作符调用而已?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP