在任何地方都没有使用下面的东西,但这个问题在我脑海中仍然存在很长时间。
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
以避免指针变更)。
答案 0 :(得分:8)
void* operator new (const size_t n);
void* operator new (size_t n);
这两个是operator new
完全相同的声明。唯一的区别是,如果它是一个定义,那么将允许或不允许在函数体内修改n(这与调用者无关,因为参数是通过值传递的)。由于这是一个实现细节,标准没有谈论它。
请记住,函数声明中会忽略顶级const。它们只与定义有关。
答案 1 :(得分:6)
两种情况下,[{1}}和普通const std::size_t
的参数类型都是std::size_t
。该标准规定,在声明(后面的定义)中处理函数签名时,std::size_t
将从该类型中删除。具体
段落在§8.3.5/ 3中:
[...]在生成参数类型列表之后,会对这些类型进行多次转换以确定函数类型。将删除修改参数类型的任何cv限定符。 [示例:类型void()(const int)变为void()(int) - end example]
现在,在函数的定义中,const
确实具有您建议的效果:阻止您修改参数。您可以使用const
参数自由实施operator new
。另一方面,强制执行基本上没用。正如其他人所提到的那样,参数为const的事实可以通过将其复制到另一个变量并使用该变量来破坏。如果没有为语言添加真正的价值,那么在编译器中添加额外的验证负担是没有意义的。
答案 2 :(得分:2)
非参考参数的约束仅具有微不足道的重要性。
标准从来电者的角度定义了“重要”事物。
这些by-value参数的constness不会也不能更改使用它们的任何代码。实施者可以照顾好自己。
更新:如果您愿意,可以这样写。
int f (const int);
int f (int) {return 0;}
int main () {
int i;
f (i);
}
我没有上述任何错误。继续并按照你的size_t: - )
预期异议:此f
代表operator new
或其他任何内容。所以我们有一个矛盾的声明/定义,但编译器不会抱怨。为什么?因为没关系。
答案 3 :(得分: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
关于复制到函数中的参数(通过值传递)不强制使用该值 - 该函数可以创建可写副本并更改该副本。
答案 4 :(得分:1)
您已经在operator new
收到了很多好的答案。 不使size
参数成为operator new
const的另一个论点:重写的实现可能希望分配比请求的空间更多的空间,例如cookie,保护字,等
同样可以为运算符删除辩护,其中它应该是void delete(void * const); (添加const以避免指针被更改)。
在大多数使用虚拟内存的现代操作系统上,free
不一定会将已分配的内存释放到操作系统。那个记忆可能仍然在程序的虚拟空间中。一个迂腐的覆盖者可能希望在删除它之前用绝对垃圾填充指向的存储器,以进一步使调用函数对该存储器的后续使用无效。调用函数在删除之后不能使用指向内存,那么为什么要用不必要的限制来阻塞operator delete
呢?