5

我只是在移植一些旧代码:

#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)

任何有关解码的帮助将不胜感激。

4

2 回答 2

7

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

new-placement 语法用于为分配函数提供附加参数。如果使用,则在通过组装由请求的空间量(第一个参数)和 new-expression 的 new-placement 部分中的表达式(第二个和后续参数)组成的参数列表创建的函数调用上执行重载决议. 这些参数中的第一个具有 size_t 类型,其余参数具有新放置中表达式的相应类型。

[示例:
— new T 导致调用 operator new(sizeof(T)),
— new(2,f) T 导致调用 operator new(sizeof(T),2,f),
— new T[ 5] 导致调用 operator 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>,它只是另一个接受 avoid*并将其作为分配结果返回的重载。

于 2011-01-13T20:24:37.090 回答
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);

如果没有 extra &,内部赋值的左右两边在类型上将不匹配:*(ptr)是一个double, while the result of placement new would be adouble*`。

于 2011-01-13T20:31:00.657 回答