命名空间中的operator new

11
namespace X
{
  void* operator new (size_t);
}

出现错误消息:

error: ‘void* X::operator new(size_t)’ may not be declared within a namespace

这是不是GCC编译器的一个错误?在旧版 GCC 中似乎可以正常工作。有什么想法为什么不能使用?

用例: 我想要为类只允许自定义operator new/delete,并且希望禁止全局 new/operator。为了捕获编译器错误而不是链接器错误,我编写了以下代码:

namespace X {
  void* operator new (size_t);
}
using namespace X;

这适用于较旧版本的gcc,但不适用于新版本。


这是一个与 http://stackoverflow.com/questions/1568168/testoperator-new 重复的问题吗? - Nemo
1
如果您想为类使用自定义运算符,请给它们一个具有该自定义运算符的公共基类。 - sharptooth
@sharptooth 如果这些类位于不同的第三方库中,则该方法毫无用处!!! - Enerccio
2个回答

14

这是不被允许的,因为它没有意义。例如,你有以下情况:

int* ptr = 0;

namespace X {
    void* operator new (size_t);
    void operator delete(void*);
    void f()
    {
       ptr = new int();
    }
}

void f()
{
    delete ptr;
    ptr = 0;
}

那么现在应该如何删除ptr - 使用全局命名空间中的operator delete()还是使用特定于namespace X的命名空间中的operator delete()?C++没有可能推断出来。


我已经发布了一个用例。还有其他用例,其中一个可能只想在namespace范围内使用该运算符。 - iammilind
请参考您提到的g++错误报告中的讨论。这是标准所禁止的。 - Nemo
+1,同意@sharptooth的观点(我之前也考虑过这个问题,但是我当时正在使用这个重载函数来完成其他任务)。 - iammilind
有一种可能的方式,C++ 应该首先查找 *ptr 所属的命名空间。这是全局命名空间,因为 ptr 的类型是 int*。因此,delete 应该使用全局运算符。但是,在任何 namespace X { ... } 中的类中,它应该首先检查 X::operator new,如果不存在,则使用全局的 ::operator new。这是如此微不足道,如此明显!毫不奇怪它在 C++ 中不存在。 - peterh

8
@Sharptooth的答案更有意义,如果我们考虑标准中的这个部分:3.7.3.1 分配函数 [basic.stc.dynamic.allocation]

[...] 分配函数应该是一个类成员函数或全局函数;如果在除全局作用域之外的命名空间作用域内声明了一个分配函数或在全局作用域中声明了静态的分配函数,则程序是不合法的。[...]

以上限制可能是出于@sharptooth所指出的原因而实施的。

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