当前位置: 首页 > 知识库问答 >
问题:

g 4.9.0允许我们在布局分配中使用操作符delete[](void*,size_t)

何嘉运
2023-03-14

我使用的是g 4.9.0和N3797工作草案。我写了以下简单示例:

#include <iostream>
#include <cstdlib>

using namespace std;

struct A
{
    void* operator new[](size_t t, size_t)
    {
        cout << "allocation" << endl;
        return ::operator new[](t);
    }

    void operator delete[](void *p, size_t t)
    {
        cout << "deallocation" << endl;
        :: operator delete[](p);
    }
};

int main()
{
    A *a = new (90) A[5];
    delete [] a;
}

演示

该示例必须反映3.7.4.2/2节中的以下脚注规则:

全局操作符delete[]只有两个参数,第二个参数的类型是std::size_t,这是一个常见的解除分配函数。37

37)此解除分配函数排除使用分配函数空运算符new(std::size_t,std::size_t)作为位置分配函数

但事实并非如此。这是一个错误或脚注只是对实现者的建议吗?

共有2个答案

彭宏深
2023-03-14

我相信你得到了未定义的行为。我认为如果构造函数失败并且必须释放数组,则无法区分正确放置的删除函数和大小的删除函数。

钦英发
2023-03-14

这是非法的,编译器应该发出诊断信息。从5.3.4 [expr.new]/p22,增加了强调:

如果放置解除分配函数具有相同数量的参数,并且在参数转换(8.3.5)后,除第一个参数类型外,所有参数类型都相同,则放置解除分配功能的声明与放置分配函数的声明匹配。如果查找找到单个匹配的解除分配函数,则将调用该函数;否则,将不调用解除分配函数。如果查找发现通常的解除分配函数(3.7.4.2)的双参数形式,并且该函数(被视为放置解除分配函数)将被选择为分配函数的匹配项,则该程序是病态的。对于非放置分配函数,使用常规解除分配函数查找来查找匹配的解除分配函数(5.3.5)[示例:

struct S {
     // Placement allocation function:
    static void* operator new(std::size_t, std::size_t);
    // Usual (non-placement) deallocation function:
    static void operator delete(void*, std::size_t);
};
S* p = new (0) S; // ill-formed: non-placement deallocation function matches
                  // placement allocation function

—结束示例]

Clang在您的代码上生成错误。

但是,请注意,与全局运算符删除运算符删除[]不同,作为类成员的双参数运算符删除运算符删除[]不一定是通常的释放函数(§3.7.4.2[basic.stc.dynamic.deallocation]/p2):

如果类<code>T<code>具有名为<code>运算符delete<code>的成员解除分配函数,且只有一个参数,则该函数是通常的解除分配函数。如果类<code>T,则该函数是一个常见的解除分配函数。类似地,如果类<code>T的成员解除分配函数,且只有一个参数,则该函数是一个普通的(非放置)解除分配函数。如果类T没有声明这样一个<code>运算符delete[],而是声明了一个名为<code>operator delete[]的成员解除分配函数,该函数正好有两个参数,其中第二个参数的类型为<code>std::size_T,则该函数是一个常见的解除分配函数。

因此,与全局释放函数不同,如果您声明一个成员运算符ete[](val*),那么运算符ete[](val*, std::size_t)不再是一个常见的释放函数,而是一个放置释放函数:

struct A
{
    void* operator new[](size_t t, size_t)
    {
        cout << "allocation" << endl;
        return ::operator new[](t);
    }

    void operator delete[](void *p)
    {
        cout << "deallocation - usual" << endl;
        :: operator delete[](p);
    }
    void operator delete[](void *p, size_t t)
    {
        cout << "deallocation - placement" << endl;
        :: operator delete[](p);
    }
};

并且 clang 不再报告此代码上的错误。

 类似资料:
  • 问题内容: AsicII表:http://www.asciitable.com 下面的代码打印出相应字符的Dec值,例如“ 123”-> 49 50 51 但是我注意到java是一种强类型语言,这意味着必须在编译时进行所有转换,但是代码如何知道如何以及何时将char转换为AsicII表中正确的Dec值呢?我弄乱了任何Java /编程基础知识吗? 问题答案: A 只是一个无符号的16位数字,因此,由

  • delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。(MDN) delete 操作符可以删除对象的一个属性。 JavaScript 中的关键字与其他语言略有不同,如 C++ 中的 delete 关键字会释放内存,JavaScript中不会,只有当一个值的引用归零时,才会被释放。 1. 使用 delete delete 操作符在与操作数运算结束后,会返回一个布尔

  • Dockerfile文件 docker撰写。yml公司 命令 错误: 步骤6:运行systemctl start httpd。服务--- Obs:在windows 7上运行:( 有小费吗?

  • 问题内容: 我正在尝试在用户空间中使用mmap读取“ mem_map”开始的物理内存。它是一个包含所有物理页面的数组。这是一台运行3.0内核的i386计算机。 代码是这样的: 我以此为根。输出为: 可以肯定的是,我搜索了问题并将以下行添加到我的/etc/sysctl.conf文件中: 但这也不起作用。 谁知道为什么不允许这样的mem_map操作,以及如何解决呢? 谢谢。 问题答案: 听起来好像内核

  • 当我试图打开索引时。php在浏览器中我看到错误: 在error.log: 2013/11/04 22:40:07[错误]3435#0:*4发送到stderr的FastCGI:“无法打开主脚本:/var/www/index.php(不允许操作)”,同时从上游读取响应头,客户端:10.0。2.2,服务器:localhost,请求:“GET/HTTP/1.1”,上游:fastcgi://127.0.0.

  • 本文向大家介绍JavaScript中诡异的delete操作符,包括了JavaScript中诡异的delete操作符的使用技巧和注意事项,需要的朋友参考一下 delete这个操作符呢,在javascript中不是很常用,但是他的特性的确很诡异。 1,删除对象的属性,代码: 那么到底delete删除的是对象的属性还是对象的属性值呢,我开始觉得删除的应该是值,因为结果是undefined,而没有报错。但