C ++允许重载operator new
- 全局和每个类 - 通常operator new
,operator new[]
分别与new[]
语句和展示位置operator new
一起使用。
这三个中的前两个通常因使用自定义分配器和添加跟踪而过载。但是放置operator new
似乎很简单 - 它实际上什么也没做。例如,在Visual C ++中,默认实现只返回传递给调用的地址:
//from new.h
inline void* operator new( size_t, void* where )
{
return where;
}
它还能做什么?为什么以及如何明智地超载展示位置operator new
?
答案 0 :(得分:16)
正确的答案是您无法替换新的运营商展示位置。
§18.4.1.3安置表格
这些函数是保留的,C ++程序可能无法定义替换标准C ++库中版本的函数。
基本原理:分配和释放运算符的唯一目的是分配和释放内存,因此当给定内存时,不应再做任何事情。 (该标准特别指出这些功能“故意不执行任何其他操作。”)
答案 1 :(得分:4)
从技术上讲,展示位置operator new
是除了所需内存大小之外还需要其他参数的operator new
。
因此,new(std::nothrow) X
使用展示位置operator new
,new(__FILE__, __LINE__) X
也是如此。
覆盖operator new(size_t, void*)
的唯一原因可能是添加跟踪信息,但我认为对此的需求非常低。
答案 2 :(得分:3)
One example在Stroustrup的常见问题解答中。
答案 3 :(得分:1)
最明显的覆盖是复制此实现。
另一个明智的做法是添加一些检查(例如,验证请求区域内没有“绑定标记”)。
然而,我认为,只要你覆盖其他的(对于给定的类),由于名称查找的机制(或者不覆盖它以防止其使用,)重点超过你必须覆盖它。那也没关系,但这是一个有意识的决定。)答案 4 :(得分:1)
为预留区域定义自己的内存管理是一个不错的用途。
对于相同的物理数据(不需要移动数据)具有不同的视图是其他间接使用。 它还允许您将结构化文件作为缓冲区上的字符读取,然后通过在缓冲区上定义该类的对象来叠加其逻辑结构。 这个东西与文件的内存映射相结合,可以大大提高性能。 内存映射硬件...... 所以,千件申请!
答案 5 :(得分:0)
我见过一个例子,其中两个参数new []被覆盖以返回预先填充作为附加参数传递的char的内存块。我不记得使用的原始代码(可能是memset()),但它在功能上是这样的:
#include <iostream>
#include <algorithm>
#include <new>
void* operator new [](size_t n, char c)
{
char* p = new char[n];
std::fill(p, p+n, c);
return p;
}
int main()
{
char* p = new('a') char[10];
std::cout << p[0] << p[1] << ".." << p[9] << '\n';
}
虽然我猜这不会被称为“展示位置”,因为它不会执行展示位置。如果模板化它可能是有用的,它可以构建任何类型的数组,填充了作为第二个参数传递的对象的副本......但是,无论如何,我们都有容器。
答案 6 :(得分:0)
我不确定这个问题,但是以下内容覆盖了班级级别的新位置:
struct Bar {
void* operator new(size_t /* ignored */, void* where) throw() { return where; }
};
int main() {
char mem[1];
Bar* bar = new(mem) Bar;
}
我相信这是合法的C ++(并且使用gcc 4.4.6编译并运行良好)。
您可以根据需要随意更改此运算符的实现(包括删除throw()
子句,这意味着编译器在调用构造函数之前不再检查where
指针的null 。尽管小心。但
§18.4.1.3很有意思。我相信这只适用于全局运算符的新函数,而不是特定于类的函数。
答案 7 :(得分:0)
放置新重载的最重要的额外功能是检查地址对齐。
例如,假设某些类需要16字节对齐。开发人员重载新的,新的[],删除和删除[] - 只是为了确保所有内容都正确对齐。
当他试图将他的类用于使用放置新的库的时候,一切正常。图书馆不知道是否需要/什么对齐类和地址它试图“放置”对象可能不一致 - 大繁荣。
这种情况的最简单的例子 - 尝试使用std :: vector&lt; T&gt;其中T需要非标准对齐。
对于placement new的重载允许检测指针是否未对齐 - 可能会节省数小时的调试时间。
答案 8 :(得分:-1)
我的主要用途是创建大量对象。它的性能要好得多,并且在整个块中分配内存的开销较小,即使用Win32中的VirtualAlloc(编程窗口时)。然后,您只需将该块中的ptr传递给每个对象放置,例如:
char *cp = new char[totalSize];
for(i = 0; i < count; i++, cp += ObjSize)
{
myClass *obj = new(cp) myClass;
}