C++ Primer第5版:重载operator new和operator delete

3
请问有人能为我解释一下《C++ Primer第五版》中的这一段话吗?
术语:new表达式与operator new函数
库函数operator new和operator delete的名称容易引起误解。与其他操作符函数(如operator=)不同,这些函数不会重载new或delete表达式。事实上,我们无法重新定义new和delete表达式的行为。
新表达式总是通过调用operator new函数获取内存,然后在该内存中构造对象来执行。删除表达式总是通过销毁对象,然后调用operator delete函数释放对象使用的内存来执行。
通过提供我们自己的operator new和operator delete函数定义,我们可以更改内存的分配方式。但是,我们无法改变new和delete运算符的基本含义。
我看不出operator new或operator delete与其他重载的运算符(如赋值运算符=)之间的区别。所以“名称容易引起误解”是什么意思呢?我们都知道我们不能覆盖像fObj + fObj这样的表达式,但我们重载的是运算符而不是表达式本身。
实际上,我认为这一段话本身就很具有误导性。毕竟,我们可以“滥用”任何可重载运算符,并从中获得operator new和operator delete,那么他在这段话中的意思是什么呢?谢谢!
1个回答

6

C++中的大多数操作符没有任何明确的语义或要求,唯一的真正例外是operator newoperator delete,由于它的专门用途,这就是所指的内容。

例如,让我们考虑operator==

尽管惯例上(也是明智的做法)让此操作符执行某种比较并返回一个bool来表示相等性,但实际上这并不是C++语言所要求的。

事实上,完全可以定义operator==来返回与之完全无关的东西--也许是一个int,一个std::string,或者更奇怪的std::tuple。当然,它也不需要实际执行任何比较。

实际上,C++中大多数操作符的语义是通过惯例而非语言本身微弱地被要求的。

这与operator newoperator delete形成对比。在C++中,new表达式将始终从operator new调用返回的指针开始一个动态对象的生命周期。无论是针对放置新表达式new (p) T{...},使用全局new操作符的new T{...}还是一些自定义operator newnew(args,...) T{...},它都必须返回某种指针来开始T的生命周期。

同样,delete必须结束该生命周期,并调用operator delete来释放该生命周期的底层存储。这实际上强制了operator newoperator delete的语义执行某种分配机制和某种清理机制。无法像operator==的情况那样定义newdelete来做一些奇怪的事情,因为调用这些操作符的暗示行为将会崩溃(如果它可以编译的话)。

这就是为什么引用提到operator new/operator delete的行为无法被重新定义;基本含义将始终固定的原因。


2
例如,您可以使用operator<<operator>>执行I/O操作,而不是位移操作。当然,任何理智的人都不应该考虑这样做。 - Hong Ooi
嗯,->也是一个例外,,无法被重载。 - Yakk - Adam Nevraumont
@Yakk-AdamNevraumont,“运算符”可以被重载,你应该看看标准库编写者为避免可能的重载所做的奇怪代码。参考 - https://en.cppreference.com/w/cpp/language/operators - Richard Critten
@Yakk-AdamNevraumont 你提到了一个很好的观点,关于 operator -> -- 尽管这并不是非常严格的。从技术上讲,operator-> 只需要返回实现了 -> 的东西 -- 这将是一个指针或类似指针的类型(如迭代器、智能指针等)。 - Human-Compiler
打字错误,应该是 .。对于 ->,它会以一种奇怪的递归方式应用。 - Yakk - Adam Nevraumont

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