在历史代码中不寻常地使用新的。这是什么意思?

时间:2011-01-13 20:09:43

标签: c++ new-operator legacy-code placement-new

我只是移植一些旧代码:

#define NewArrayOnHeap(TYPE, COUNT, HEAP, NEWPTR, ERROR) \
((*(NEWPTR) = new ( #TYPE "[" #COUNT "]", __alignof(TYPE), (HEAP), &hr, (ERROR)) TYPE[COUNT] ), hr)

原来应该定义他们自己的神奇new运算符。我很好奇这种用法。

使用示例

int main()
{
    void*   heap = /* Don't know how to define this */
    double* ptr;
    HRESULT hr;

    hr = NewArrayOnHeap(double, 10, heap, ptr, "Help /* Just guessing here */");
}

当我使用g++ -E获取预处理器输出时,它是:

int main()
{
    double* ptr;
    HRESULT hr;

    hr = ((*(ptr) = new ( "double[ 10 ]", __alignof(double), (NULL), &hr, ("Help")) double[10] ), hr);
}

这看起来更像是placement new

但现在这是一个重载的新调用(带有一些时髦的参数,一个五个参数new调用),或者这里是逗号运算符的逗号,因此它减少到("Help")(这不会没有意义。

历史上(甚至现在)new是否允许有两个以上的参数(size, hint)

任何有关解码的帮助都将受到赞赏。

2 个答案:

答案 0 :(得分:7)

您要查看的部分是§5.3.4/ 11-12,在此处解释:

  

new-placement语法用于为分配函数提供其他参数。如果使用,则对通过组合参数列表创建的函数调用执行重载解析,该参数列表包括请求的空间量(第一个参数)和new-expression的新放置部分中的表达式(第二个和后续参数) 。第一个参数的类型为size_t,其余参数在new-placement中具有相应的表达式类型。

     

[实施例:
   - new T导致操作员调用new(sizeof(T)),
   - new(2,f)T导致操作员调用new(sizeof(T),2,f),
   - 新T [5]导致操作员new的调用,以及
   - new(2,f)T [5]调用operator new [](sizeof(T)* 5 + y,2,f)。]

因此,要正确使用您的宏,需要在某处定义类似于operator new的重载:

void* operator new[](size_t, const char*, size_t, void*, HRESULT*, const char*);

我怀疑使用给它的信息来分配满足对齐要求的内存(可能来自预先分配的源),同时记录此分配并在无法进行分配时提供自定义错误消息。

就个人而言,我觉得很糟糕。 :)


您所指的典型“placement new”运算符在<new>中定义,并且只是另一个接受void*的重载并将其作为分配结果返回。

答案 1 :(得分:3)

我的假设是它是新的放置,并且所有5都是重载的参数。在我的解释中,其中一个参数是&hr,这是一个错误代码,然后用作operator,的第二个参数,以提供该值作为结果值。

我不认为您对宏的使用是正确的,特别是我认为NEWPTR旨在成为实际初始化指针的地址,也就是说,调用代码应该是:

hr = NewArrayOnHeap(double, 10, heap, &ptr, "Help");

将进行扩展:

hr = ((*(&ptr) = new ( "double[ 10 ]", __alignof(double), (NULL), &hr, ("Help")) double[10] ), hr);

如果没有额外的&,内部作业的左侧和右侧的类型将不匹配:*(ptr)double, while the result of placement new would be a双*。