::operator new[]()和::operator new()有什么不同?

3

我需要从先前分配的内存块构造一个对象数组。但是,我无法理解::operator new[]()::operator new()在用户分配该块时有何不同,因为两者都需要块的大小。在下面的示例中,使用任何一个似乎都具有相同的效果。我是否遗漏了什么?

class J {
};

int main() {
    const int size = 5;

    {
        J* a = static_cast<J*> (::operator new[](sizeof (J) * size));
        for (int i = 0; i < size; i++)
            new (&a[i]) J();
        for (int i = 0; i < size; i++)
            a[i].~J();
        ::operator delete[] (a);
    }

    {
        J* a = static_cast<J*> (::operator new(sizeof (J) * size));
        for (int i = 0; i < size; i++)
            new (&a[i]) J();
        for (int i = 0; i < size; i++)
            a[i].~J();
        ::operator delete (a);
    }
}

可能是[What's the purpose of having a separate "operator new[]"?]的重复问题。(https://dev59.com/t3E95IYBdhLWcg3wApHl) - Cheers and hth. - Alf
我认为这不是同一个问题。那个帖子的楼主知道差异在哪里,只是想问为什么。而这个帖子的楼主则是在询问差异在哪里。对于精通C++的人来说,很容易混淆,但这绝对不是同一个问题。 - littleadv
依照我的看法(在考虑了你的评论之后仍然如此),这绝对是完全相同的问题。 - Cheers and hth. - Alf
2个回答

3
您误用了new
使用new []的目的是为分配的每个数组元素调用构造函数。 delete [] 同样会为析构函数执行相同操作。
您正在使用放置 new 并手动调用构造函数和析构函数,从而错过了整个重点。

你能进一步解释吗,因为我不明白你的意思。我想故意不使用new和delete[]。如果必须单独调用::operator new来构造对象数组,则我看不出两种方法之间有任何区别。 - Martin
在我看来,原帖作者似乎已经知道了这一点。然而,这个问题似乎是早先提出的问题的确切重复。因此,我投票关闭了它。 - Cheers and hth. - Alf
@Martin,如果你使用new作为malloc的替代品-没有区别。这不是new通常应该使用的方式(尽管在C++中允许)。 - littleadv
我觉得我可能让你困惑了,因为我在示例中还添加了delete[]和delete(),而我的问题实际上是关注分配和构建对象数组的分离。假设您正在处理一个对象池,在其中一次性分配内存,但经常进行构建和析构。如果我理解正确,那么从用户的角度来看没有区别。只是出于我的好奇心,那么实现方面有什么区别呢? - Martin
@Martin - new 的目的在于在分配时构建。如果您有动态数组,请使用 std::vector,可以自定义分配器(带或不带),最终会减少到 new。我再重复一遍,因为似乎还不清楚,如果您使用 new 来替换 malloc,那么没有区别,但这不是 C++ 中应该使用 new 的方式 - littleadv

3
它们都是分配函数,因此它们都必须返回适合请求大小的存储空间(这里是sizeof(J) * size)。这就是为什么它们在您的代码中没有区别的原因。
它们的不同之处在于operator new是在非数组new表达式中查找的分配函数(例如new J),而operator new[]是在数组new表达式中查找的分配函数(例如new J[1])。这允许自定义,如果程序有一种特定的策略来为数组分配内存,该策略与为单个对象分配内存的策略不同。如果不需要这样的自定义,则operator new[]可以直接委托给operator new(实现提供的分配函数,即::operator new::operator new[]也是这样规定的)。所以对于您的代码来说,这种差异并不重要。

值得一提的是,new J[1];通常会从分配函数请求超过sizeof(J) * 1字节的内存。 - Kerrek SB
@KerrekSB 我认为新表达式(除了常规的placement new)并不是重点。 - Luc Danton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接