用于堆内存分配的新运算符
Posted
技术标签:
【中文标题】用于堆内存分配的新运算符【英文标题】:new operator for memory allocation on heap 【发布时间】:2011-06-23 22:19:12 【问题描述】:我正在查看 new 运算符的签名。即:
void* operator new (std::size_t size) throw (std::bad_alloc);
但是当我们使用这个操作符时,我们从不使用强制转换。即
int *arr = new int;
那么,在这种情况下,C++ 如何将void*
类型的指针转换为int*
。因为,即使malloc
返回void*
,我们也需要显式使用强制转换。
【问题讨论】:
【参考方案1】:operator new
和 new
运算符在 C++ 中存在非常细微的区别。 (再读一遍……顺序很重要!)
函数operator new
是C 的malloc
函数的C++ 模拟。它是一个原始内存分配器,其职责仅是生成一块用于构造对象的内存块。它不调用任何构造函数,因为那不是它的工作。通常,您不会看到在 C++ 代码中直接使用operator new
;看起来有点奇怪。例如:
void* memory = operator new(137); // Allocate at least 137 bytes
new
运算符是一个关键字,负责为对象分配内存并调用其构造函数。这是 C++ 代码中最常见的情况。当你写
int* myInt = new int;
您正在使用 new 运算符分配一个新整数。在内部,new
运算符的工作方式大致如下:
-
使用
operator new
分配内存来保存请求的对象。
调用对象构造函数,如果有的话。如果这引发异常,请使用 operator delete
释放上述内存,然后传播异常。
返回一个指向新建对象的指针。
因为new
运算符和operator new
是分开的,所以可以使用new
关键字来构造对象而无需实际分配任何内存。例如,著名的 placement new 允许您在用户提供的内存中的任意内存地址构建对象。例如:
T* memory = (T*) malloc(sizeof(T)); // Allocate a raw buffer
new (memory) T(); // Construct a new T in the buffer pointed at by 'memory.'
通过定义自定义operator new
函数重载new
运算符,您可以通过这种方式使用new
;您指定分配的发生方式,C++ 编译器会将其连接到 new
运算符。
如果您好奇,delete
关键字的工作方式相同。有一个名为operator delete
的释放函数负责释放内存,还有一个delete
运算符负责调用对象析构函数和释放内存。但是,operator new
和 operator delete
可以在这些上下文之外使用,例如代替 C 的 malloc
和 free
。
【讨论】:
第二步应该是“调用对象构造函数,如果有的话。如果这抛出任何异常,释放上面的内存并传播异常。” @GMan- 感谢您发现这一点!我的错。我会解决的。 另外,你能推荐一些我能找到这样珍珠的书吗? @Chander Shivdasani- 很高兴为您提供帮助;不要忘记接受答案。 ;-) 这颗智慧之珠基于 Scott Meyers 对“Effective C++, 3rd Edition”中新内容的讨论,该书被广泛认为是 C++ 方面最好的书籍之一。它将把你从一个优秀的 C++ 编码员转变为一个伟大的 C++ 编码员,并让你接触到各种你从未想过可以用 C++ 表达的酷想法。我强烈推荐它。 非常感谢...我一定会得到它的副本。【参考方案2】:您将new
表达式与operator new()
函数混淆了。当前者被编译时,编译器会生成一个对operator new()
函数的调用,并传递足够的大小来容纳new
表达式中提到的类型,然后返回该类型的指针。
【讨论】:
致那些投反对票的人——这个答案有什么问题?这似乎完全正确。以上是关于用于堆内存分配的新运算符的主要内容,如果未能解决你的问题,请参考以下文章
如果已知 void* 分配大小,如何将确切的内存大小传递给 free()