c++ - `operator delete` 带大小参数和不带大小参数 : which one is chosen when both are available?

标签 c++ operator-overloading c++14 language-lawyer delete-operator

当我在 GCC 和 Clang 中运行此代码示例时

struct S
{
  int a;        

  void *operator new(size_t s) 
  { 
    std::cout << "new " << s << std::endl;
    return ::operator new(s); 
  }

  void operator delete(void *p, size_t s) noexcept 
  { 
    std::cout << "delete " << s << std::endl;
    ::operator delete(p);
  }

  void operator delete(void *p) noexcept
  { 
    std::cout << "delete " << "none" << std::endl;
    ::operator delete(p);
  }
};

int main()
{
  S *p = new S;
  delete p;
}

我从 GCC 和 Clang 得到以下输出

new 4
delete none

这意味着编译器选择了 operator delete 的“无大小”版本。

但是,如果我尝试使用全局替换的 operator newoperator delete 函数进行类似操作

struct S
{
  int a;        
};

void *operator new(size_t s)
{
  std::cout << "new " << s << std::endl;
  return std::malloc(s);
}

void operator delete(void *p, size_t s) noexcept
{
  std::cout << "delete " << s << std::endl;
  std::free(p);
}

void operator delete(void *p) noexcept
{
  std::cout << "delete " << "none" << std::endl;
  std::free(p);
}

int main()
{
  S *p = new S;
  delete p;
}

从 GCC 我得到

new 4
delete 4

我从 Clang 得到

new 4
delete none

我知道类内 operator delete 的“sized”版本自 C++98 以来一直存在于 C++ 中,但纵观 C++98,我似乎无法做到找到第一个示例中应选择哪个版本的 operator delete 问题的明确答案。甚至指定了吗?

第二个示例中的 C++14 及其“大小”版本的全局 operator delete 又如何呢?语言是否说明应该选择哪个版本?

最佳答案

这是 CWG issue 255 , 追溯到 2000 年。引用它的前提:

Paragraph 4 of 15.5 [class.free] speaks of looking up a deallocation function. While it is an error if a placement deallocation function alone is found by this lookup, there seems to be an assumption that a placement deallocation function and a usual deallocation function can both be declared in a given class scope without creating an ambiguity. The normal mechanism by which ambiguity is avoided when functions of the same name are declared in the same scope is overload resolution; however, there is no mention of overload resolution in the description of the lookup. In fact, there appears to be nothing in the current wording that handles this case. That is, the following example appears to be ill-formed, according to the current wording:

struct S {
    void operator delete(void*);
    void operator delete(void*, int);
};
void f(S* p) {
    delete p;    // ill-formed: ambiguous operator delete
}

该问题的状态目前为“正在起草”,在撰写此答复时似乎仍未解决。没有关于释放函数的重载决议的措辞。

Clang 和 GCC 似乎是在任意选择。我认为发出某种关于运算符模棱两可的诊断会更好。

关于c++ - `operator delete` 带大小参数和不带大小参数 : which one is chosen when both are available?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56368799/

相关文章:

c++ - 如何检查两个不同类型的 vector 是否相等

c++ - 我怎样才能索引一个集合并允许每个索引的变量有一个自定义的 setter ?

c++ - 自定义元素的迭代器在 vector 中

c++ - 如何使用 boost::unordered_map 的 boost std::vector 序列化/反序列化

c++ - 类中的指针私有(private)属性,其中此类在 vector 中使用,生成错误双重释放或损坏

c++ - 复制构造函数是可行的重载吗?

c++ - 为什么模板参数替换的顺序很重要?

c++ - 在 QT 中,如何在自定义 Widget 中定义 Layout 的几何图形

c++ - 函数比较器可以是静态函数吗?

c++ - 如何访问嵌套在命名空间内的未命名空间变量?