为什么运算符 new 不被迫将论证视为"常量size_t"?
Why isn't operator new forced to take argument as "const size_t"?
没有在任何地方使用下面的东西,但这个问题仍然在我的脑海中徘徊了很长时间。
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
以避免指针被更改)。
void* operator new (const size_t n);
void* operator new (size_t n);
这两个是operator new
的完全相同的声明。唯一的区别是,如果它是一个定义,则允许或不允许在函数体内修改n(这与调用者无关,因为参数是按值传递的)。因为这是一个实现细节,所以标准没有讨论它。
请记住,顶层const在函数声明中被忽略。它们只在定义中相关
const std::size_t
和普通std::size_t
的参数类型都是std::size_t
。标准规定,在声明(后面的定义)中处理函数签名时,从类型中删除const
。具体的段落见§8.3.5/3:
[…在生成参数类型列表后,对这些类型进行若干转换以确定函数类型。任何修改参数类型的cv限定符都将被删除。[示例:类型void()(const int)变为void()(int) -end示例]
现在,在函数的定义中,const
确实具有您提出的效果:阻止您修改实参。您可以自由地使用const std::size_t
参数来实现operator new
。另一方面,强制执行基本上是无用的。正如其他人提到的,实参是const的事实可以通过将其复制到另一个变量并使用该变量来改变。当它不能给语言带来真正的价值时,给编译器增加额外的验证负担是没有意义的。
好,让我们假设它是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
对复制到函数中的参数(按值传递)不强制使用该值——函数可以创建一个可写副本并修改该副本。
非引用参数的Const-ness只是次要的。
标准从调用者的角度定义了"重要"的事情。
这些按值参数的一致性不会也不能改变使用它们的任何代码。实现者可以自己照顾自己。
更新:如果你愿意,你可以这样写
int f (const int);
int f (int) {return 0;}
int main () {
int i;
f (i);
}
上面我没有得到任何错误。继续创建size_t:-)
预料到反对意见:这里f
代表operator new
或其他什么。所以我们有一个矛盾的声明/定义,但编译器没有抱怨。为什么?因为这并不重要
您已经在operator new
上收到了许多很好的答案。对于不是使size
参数为operator new
const的另一个参数:重写实现很可能希望分配比请求更多的空间,例如cookie,保护字等。
operator delete也可以采用同样的方法,它应该void operator delete (void* const);(添加const以避免指针被更改)。
在大多数使用虚拟内存的现代操作系统上,free
不一定会释放分配给操作系统的内存。这些内存很可能仍然在程序的虚拟空间中。迂腐的重写很可能希望在删除指向内存之前用绝对垃圾填充它,以进一步使调用函数随后对该内存的使用无效。调用函数在删除指向内存后不能使用它,那么为什么要用不必要的限制来限制operator delete
呢?
- #定义c-预处理器常量..我做错了什么
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 通过多个头文件使用常量变量
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 大于65535的C++数组[size]引发不一致的溢出
- 是默认情况下分配给char数组常量的值
- 为什么(-1)%vector::size()总是返回0
- 私有类型的静态常量成员
- 类似枚举的计算常量
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- vector::size() 如何在常量时间内返回向量的大小
- 错误:"SIZE"在使用模板<类 T、int MAX_SIZE >时无法出现在常量表达式中
- 调用 size() 的常量映射<字符串,矢量<int>>导致错误
- std::map 如何提供常量 size() 操作