1

我很难消化这种语法:

void* operator new[](std::size_t, const std::nothrow_t&) throw();

虽然这仍然可以理解:

void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();

问题:

  1. 我认为new和下标[]是不同的运算符。我们如何在一个定义中组合两个运算符以重载?

  2. 还有nowthrow. 以下调用对我没有意义(关于函数的签名)。

     int * p2 = new (nothrow) int;
    

如果有人可以参考 bjarne stroustrup 书中的相关主题,那就太好了,但不是硬性要求。

更新:请尝试回答这两个问题:)

4

3 回答 3

3

new[] 和 [] 是两个完全不同的运算符。

new[] 是数组的分配运算符,[] 是数组的下标访问运算符。

new[] 是它自己的运算符,它不仅仅是结合了 '[]' 下标运算符的 'new' 分配器。

于 2012-04-06T23:06:59.917 回答
2

前两个是全球新运营商的签名。对于(很少)它的价值,operator new用于为新表达式分配空间,例如x = new T;,而operator new[]用于为新表达式分配空间,例如x = new T[count];. 它的价值“小”有一个相当简单的原因:你永远不应该使用new T[count],所以它的工作原理几乎纯粹是一个历史好奇心。

如果您愿意,您可以重载::operator new和/或提供您自己的堆分配。::operator new[]就基本要求而言,两者之间没有区别——它们都只是分配并返回一个指向所请求内存量的指针。

就目前nothrow而言,传递给的大小operator new总是由编译器根据对象的大小计算出来的,如果是新数组,则计算你给出的计数。因此,您在新表达式中指定的参数变成传递给的第二个参数operator new

为了强调一点,我在上面可能还不够清楚:operator new(and operator new[]) 被使用,但与新表达式分开(当你说类似的东西时,你在代码中的内容x = new T;)。operator new并且operator new[]非常像malloc- 他们只是分配“原始”内存。一个新的表达式1使用其中一个来分配原始内存,然后调用构造函数在该内存中分配一个对象(或多个,在 的情况下new T[count];)。这两者显然是相关的,但同样显然不是真的相同。

另一个小问题:也可以有一个operator new(或operator new[]作为类成员。这允许您为该类分配与使用全局堆的其他类不同的内存。这对于您期望的小对象来说往往是最常见的大量分配。对于这些,全局堆通常有很多您希望避免的开销。

最后,当/如果你想分配原始内存,你也可以operator new直接调用,如void *a = ::operator new(1234);. 唯一常见的地方是如果您决定自己实现某种集合类(例如,如果您想要一个循环缓冲区)。

于 2012-04-06T23:19:30.140 回答
1

new并且new[]是两个独立的运算符,与“[]”运算符没有真正的关系。delete p最好从和之间的区别中看出这一点delete[] p;您是要删除 指向的单个实例p,还是整个实例数组?

同样,new[]是一种分配整个对象数组的方法,所有对象都在同一个内存块中。

于 2012-04-06T23:07:17.220 回答