2

没有在任何地方使用下面的东西,但这个问题仍然在我脑海中很久。

void* operator new (size_t size)
{
  // distort `size` to other value
  return malloc(size);
}

知道上面对于重载可能不是一个明确定义的行为new(比如如果size减少了),为什么标准不强制编译器将其设为void* operator new (const size_t);

同样可以争论operator delete,它应该在哪里void operator delete (void* const);(添加const以避免指针被改变)。

4

5 回答 5

8
void* operator new (const size_t n);
void* operator new (size_t n);

这两个是完全相同的声明operator new。唯一的区别是,如果它是一个定义,则 n 将被允许或不允许在函数体内修改(这与调用者无关,因为参数是按值传递的)。由于这是一个实现细节,标准没有谈论它。

请记住,顶级 const 在函数声明中被忽略。它们仅在定义中相关。

于 2011-07-22T11:20:34.800 回答
6

两种情况下参数的类型,const std::size_tplainstd::size_tstd::size_t. 该标准规定,在声明中处理函数签名(稍后定义)时,const从类型中删除 。具体段落在 §8.3.5/3 中:

[...] 生成参数类型列表后,对这些类型进行若干转换以确定函数类型。任何修改参数类型的 cv 限定符都会被删除。[示例:类型 void()(const int) 变为 void()(int) —结束示例]

现在,在函数的定义中,const确实具有您建议的效果:阻止您修改参数。operator new你可以自由地用一个const std::size_t参数来实现你的。另一方面,强制执行基本上是无用的。正如其他人所提到的,可以通过将参数复制到不同的变量并使用该变量来破坏参数是 const 的事实。如果没有为语言增加真正的价值,那么给编译器增加额外的验证负担是没有意义的。

于 2011-07-22T13:02:33.523 回答
2

非引用论点的常量性仅具有边际重要性。

该标准从调用者的角度定义了“重要”的事情。

这些按值参数的常量不会也不能更改任何使用它们的代码。实施者可以照顾自己。

更新:如果你愿意,你可以这样写。

int f (const int);
int f (int) {return 0;}

int main () {
    int i;
    f (i);
}

我没有收到上述任何错误。继续并 const-ify 你的 size_t :-)

预期反对意见:这里f代表operator new或其他。所以我们有一个矛盾的声明/定义,但编译器没有抱怨。为什么?因为它只是无关紧要。

于 2011-07-22T11:14:38.693 回答
2

好吧,让我们假设它是const

void* operator new (const size_t size)
{
   size_t alteredSize = size;
   alteredSize += 10; // for whatever reason
   return malloc( alteredSize );
}

这与

void* operator new (size_t size)
{
   size += 10;
   return malloc( size );
}

const复制到函数中的参数(按值传递)不会强制使用该值 - 函数可以创建可写副本并更改该副本。

于 2011-07-22T11:16:49.553 回答
1

你已经收到了很多很好的答案operator new向const 提供参数的另一个size论点operator new:一个覆盖实现可能希望分配比请求更多的空间,例如用于 cookie、警戒词等。

对于 operator delete 也可以这样说,它应该 void operator delete (void* const); (添加 const 以避免指针被更改)。

在大多数使用虚拟内存的现代操作系统上,free不一定会将分配的内存释放给操作系统。该内存可能仍然在程序的虚拟空间中。一个迂腐的覆盖者很可能希望在删除它之前用绝对垃圾填充指向的内存,以进一步使调用函数对该内存的后续使用无效。调用函数在删除它后不能使用指向的内存,那么为什么要operator delete受到不必要的限制呢?

于 2011-07-22T13:32:22.207 回答