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

发布于 2024-10-12 11:59:49 字数 971 浏览 6 评论 0原文

我只是移植一些旧代码:

#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 调用(带有一些时髦的参数,一个五个参数的 new 调用),还是这里的逗号是逗号运算符,因此它被简化为 ("Help") (这没有意义)。

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

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

I am just porting some old code:

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

It looks like the original was supposed to define their own magical new operator. I am curious about this usage.

Example usage

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 */");
}

When I use g++ -E to get the preprocessor output, it's:

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

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

This looks slightly more like a placement new.

But is this now an overloaded new call (with some funky parameters, a five parameter new call), or are the commas here the comma operator and thus it gets reduced to ("Help") (which wouldn't make sense).

Was new historically (or even now) allowed to have more than two parameters, (size, hint)?

Any help on decoding would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执妄 2024-10-19 11:59:49

您要查看的部分是 §5.3.4/11-12,释义如下:

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

[示例:
— new T 导致调用运算符 new(sizeof(T)),
— new(2,f) T 导致调用运算符 new(sizeof(T),2,f),
— new T[5] 导致调用 new 运算符,并且
— new(2,f) T[5] 导致调用运算符 new[](sizeof(T)*5+y,2,f)。]

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

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

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

就我个人而言,我觉得很恶心。 :)


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

The section you want to look at is §5.3.4/11-12, paraphrased here:

The new-placement syntax is used to supply additional arguments to an allocation function. If used, overload resolution is performed on a function call created by assembling an argument list consisting of the amount of space requested (the first argument) and the expressions in the new-placement part of the new-expression (the second and succeeding arguments). The first of these arguments has type size_t and the remaining arguments have the corresponding types of the expressions in the new-placement.

[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, and
— new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).]

So your macro, to be used correctly, requires that somewhere there's an operator new overload defined similar to:

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

Which I suspect uses the information given to it to allocate memory (potentially from a pre-allocated source) that satisfies alignment requirements, while logging this allocation and providing a custom error message if the allocation could not be made.

Personally, I find it gross. :)


The typical "placement new" operator you're referring to is defined in <new>, and is just another overload that accepts a void* and returns that as the allocation result.

世界如花海般美丽 2024-10-19 11:59:49

我的假设是它是新的放置,并且所有 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 ,而放置 new 的结果将是 double*`。

My assumption is that it is placement new, and that all 5 are arguments to the overload. In my inerpretation, one of the arguments is &hr, which is an error code and then is used as second argument to operator, to provide that as a result value.

I don't think that your usage of the macro is correct, in particular I believe that NEWPTR is intended to be the address of the actual pointer to initialize, that is, calling code should be:

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

which would make the expansion:

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

Without the extra &, the left and right hand sides of the inner assignment would not match in type: *(ptr) is a double, while the result of placement new would be adouble*`.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文