【发布时间】:2012-01-03 10:35:18
【问题描述】:
考虑以下代码和以下问题:
/*
* GCC 4.4
*/
#include <iostream>
using namespace std;
class A {
public:
void* operator new(size_t s) {
cout << "A::operator new(size_t) called\n";
}
void operator delete(void* p) {
cout << "A::operator delete(void*) called\n";
}
void* operator new(size_t s, A* p) {
cout << "A::operator new(size_t, A*) called\n";
}
void operator delete(void* p, size_t s) {
cout << "A::operator delete(void*, size_t) called\n";
}
};
void* operator new(size_t s) {
cout << "::operator new(size_t) called\n";
}
void operator delete(void* p) {
cout << "::operator delete(void*) called\n";
}
void* operator new(size_t s, A* p) {
cout << "::operator new(size_t, A*) called\n";
}
void operator delete(void* p, size_t s) {
cout << "::operator delete(void*, size_t) called\n";
}
int main() {
A* p1 = new A(); // See question 1.
delete p1; // See question 2.
A* p2 = new (p1) A(); // See question 3.
delete p2; // See question 4.
}
下面的问题似乎有些多余。但是,我要区分的是 C++ 标准规则定义的内容和实现定义的内容。
-
operator new(size_t)将在任何情况下使用(取自 A 或全局 命名空间,无论是否默认)。还行吧。 现在尝试仅删除void* A::operator new(size_t) {}:为什么编译器会给出:错误:没有匹配函数调用‘A::operator new(unsigned 整数)’ 注意:候选对象是:static void* A::operator new(size_t, A*)
不让编译器从全局中获取
::operator new(size_t)命名空间? 为什么
operator delete(void*)比operator delete(void*, size_t)更受欢迎 (当这两个版本都存在于operator delete (void*)的同一命名空间中时)?-
如果我删除
void* A::operator new(size_t, A*),为什么代码无法编译, 尽管在全局命名空间中定义了相同版本的操作符?错误:没有匹配函数调用‘A::operator new(unsigned int, 一种*&)' 注意:候选对象是:static void* A::operator new(size_t)
为什么编译器仍然偏爱
operator delete (void*),虽然A::operator new(size_t, A*)已被使用 获得p2?
【问题讨论】:
-
这是很多问题。如果你想亲自看看n3242.pdf,我会从
5.3.4 New开始(第110页) -
无论如何我认为所有的问题都与同一个主题有关。
-
如果可能只有一个答案可以解决整个问题,那么 Q/A 格式的效果最好。当多个答案组合起来提供答案时,您会感到困惑的是要接受什么答案。这使得未来的 SO 搜索者很难/不可能找到信息。
-
我很确定这不是来自生产代码,但您可能不想在
operator new中使用std::cout(即使用于调试),因为不能保证输出操作不会分配内存(并调用operator new())。 -
出于这个原因,@Sehe,我已投票决定将其作为“不是一个真正的问题”来结束。对这个密切原因的解释提到“过于宽泛”。
标签: c++