3.7.4.2[basic.stc.dynamic.deallocation]/2 中 C++14 中的脚注 37 的原因是什么?

What's the reason for footnote 37 in 3.7.4.2[basic.stc.dynamic.deallocation]/2 in C++14?

本文关键字:脚注 C++14 是什么 basic stc deallocation dynamic      更新时间:2023-10-16

§3.7.4.2/2包含以下句子:

具有恰好两个参数的全局operator delete具有类型CCD_。类似地,具有恰好一个参数的全局operator delete[]是通常的解除分配函数。全局运算符delete[]正好有两个参数,其中第二个类型为std::size_t,是通常的解除分配功能37

37)该解除分配函数排除了将分配函数void operator new(std::size_t, std::size_t)用作职位分配功能。

我不仅不理解这个脚注的原因,而且我注意到脚注中提到的这个放置表格在§18.6.1.3放置表格[new.delete.placement]中不存在。

编辑为了验证@Sander De Dicker在回答中所说的内容,我测试了以下片段:

#include <iostream>
void* operator new  (std::size_t count, int i1, int i2, int i3){
    void *p = malloc(count);
    if (!p) throw std::bad_alloc{};
    std::cout << "operator new" << 'n';
    return p;
}
void operator delete (void* p, int j1, int j2, int j3)
{
    free(p);
    std::cout << "operator delete" << 'n';
}
class A {
public:
    A() { std::cout << "A()" << 'n'; };
    ~A() { std::cout << "~A()" << 'n'; }
};
int main()
{
    try
    {
        A *p = new(0, 0, 0) A;
        delete p;
    }
    catch (std::bad_alloc&) { exit(1); }
}

在我现有的所有3个编译器(VS2015、clang和g++)中,代码调用了位置operator new(size_t, int, int, int),但没有调用位置operator delete(void*, int, int, int),而是调用了operator delete(void*)。现在,我比发布问题时更困惑了。

实例

C.3.2[diff.cpp11.basic]解释道:

C.3.2第3条:基本概念[diff.cpp11.basic]

3.7.4.2

更改:新的常规(非配售)解除定位器

基本原理:按大小进行交易时需要。

对原始功能的影响:有效的C++2011代码可以如下声明全局放置分配函数和释放函数:

void operator new(std::size_t, std::size_t);

void operator delete(void*, std::size_t) noexcept;

然而,在本国际标准中,operator delete的声明可能与预定义的常用(非放置)operator delete(3.7.4)相匹配。如果是,则该程序格式不正确,就像类成员分配函数和释放函数一样(5.3.4)。

换言之,这是对以前的标准(C++11)的突破性更改。在C++11中,允许定义这样的operator delete,而在C++14中,程序将是不成形的。

编辑-根据评论进一步澄清

  • 18.6.1.3[new.delete.placement]列出了保留的放置表格。但是,您可以在代码中声明其他(非保留)。所以,标准的这一部分不适用于你的问题。

  • 3.7.4.2[basic.stc.dynamic.deallosition]与C++11相比有上述变化,C++11不允许放置形式operator new(std::size_t, std::size_t)operator delete(void*, std::size_t),因为后者可能与预定义的非放置operator delete匹配。C.3.2[diff.cpp11.basic]中进一步记录了这一变化

  • 您编辑后的问题已经在@T.C.的评论(1,2)中得到了解决,但为了完整起见,我将在此处包含它:没有调用自定义operator delete(void*, int, int, int)的原因是operator new(std::size_t, int, int, int)没有引发异常5.3.4[expr.new]§20-23中解释了这一点。