RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 986966
Accepted
Popa228
Popa228
Asked:2020-05-29 18:39:04 +0000 UTC2020-05-29 18:39:04 +0000 UTC 2020-05-29 18:39:04 +0000 UTC

运算符 delete 运算符的第二个参数是干什么用的?

  • 772

operator delete(void*)声明和operator delete(void*, size_t)班级有区别吗?真的需要第二个参数吗?如果是这样,为什么?

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-05-30T05:01:09Z2020-05-30T05:01:09Z

    自“经典”C++ 时代以来,函数中就一直存在第二个可选类型参数,即 在 C++98 中,可以在 中使用这样的参数,专门为单个. 也就是说,在一个特定的类中,你可以选择声明size_toperator deleteoperator delete

    operator delete(void *p);
    // или 
    operator delete(void *p, size_t s);
    

    在要删除的类提供自己operator delete的第二个类型参数重载的情况下size_t,编译器必须将要删除的内存块的正确大小传递给此类运算符,即 operator new与分配此块时传入的大小相同。

    全球operator delete没有这种可能性。

    由于重载类operator new和operator delete 基类可用于为派生类的对象分配/取消分配内存,因此语言中提供了此功能。

    struct Base
    {
      void *operator new(size_t s) 
      { 
        std::cout << "new " << s << std::endl;
        return ::operator new(s); 
      }
    
      void operator delete(void *p, size_t s) 
      { 
        std::cout << "delete " << s << std::endl;
        ::operator delete(p);
      }
    };
    
    struct Derived : Base
    {
      char buffer[1024];
    };
    
    int main()
    {
      Base *pb = new Base;
      delete pb;
    
      Derived *pd = new Derived;
      delete pd;
    }
    

    通过解析传递给operator newand的值operator delete,这些运算符可以确定分配或释放哪些可能的大小,并相应地重定向调用。

    C++98中的全局函数::operator new不存在这种可能性::operator delete,即 仅在全球范围内提供了替代品

    operator delete(void *p);
    

    但是,从 C++14 开始,也为全局函数提供了这种可能性。这样做是为了改进对不在块本身(或附近某处)中存储块大小的分配器的支持,即 对于难以从指针确定块大小的分配器。例如,对于一维对象池。此外,当两个或多个相邻的新表达式由一个operator new总大小的调用管理时(因此,对称删除表达式的处理)。

    也就是说,如果由于某种原因您希望接收::operator delete与传递给相应调用的大小相同的大小,则使用第二个类型参数::operator new声明您自己的大小。如果你对这个尺寸不感兴趣,那么就不用这样的参数来声明它。::operator deletesize_t


    同时存在两个选项的情况operator delete似乎长期处于不确定状态,是标准的缺陷。最有可能的情况是,同时提供两个选项会导致模棱两可的错误。

    • 8
  2. AlexGlebe
    2020-05-29T20:49:55Z2020-05-29T20:49:55Z

    如果程序员想要在某处手动处理内存分配,则调用该运算符。(隐藏/在文件中/无效)当调用删除对象时,将delete调用具有内存大小参数的自定义对象。

    // > g++-5 -Wall -Wpedantic -std=c++14 operdelet.cpp
    # include <iostream>
    # include <string.h>
    class A{
    int i[10];
    public:
    void    operator delete[](void * p,size_t s){
        std::cout<<"A:s="<<s<<std::endl;
        memset(p, 666,s); // зачищаю память
        :: operator delete[]( p ); }
    };
    
    class B{
    int i[100];
    public:
    virtual ~B(){}
    void    operator delete(void * p,size_t s);
    };
    
    class C:public B{
      int i[1000];
    public:
      virtual ~C(){}
    };
    
    void   B:: operator delete(void * p,size_t s){
        std::cout<<"sizeof(B)="<<sizeof(B)<<std::endl;
        std::cout<<"sizeof(C)="<<sizeof(C)<<std::endl;
        std::cout<<"B:s="<<s<<std::endl;
        memset(p, 555,s); // зачищаю память
        :: operator delete( p ); }
    
    void    operator delete(void * p,size_t s){
        std::cout<<"main:s="<<s<<std::endl;
        memset(p, 777,s); // зачищаю память
        :: operator delete( p ); }
    
    int main() {
        A * a = new A;
        B * b = new B;
        A * a7 = new A[7];
        B * c = new C ;
        delete c ;
        delete [] a7 ;
        delete b;
        delete a; }
    

    首先调用这个操作符,然后我调用标准版本。

    sizeof(B)=408
    sizeof(C)=4408
    B:s=4408
    A:s=288
    sizeof(B)=408
    sizeof(C)=4408
    B:s=408
    main:s=40
    

    第一个使用虚拟析构函数的 delete 调用表明delete来自基类的运算符不知道将删除哪个同级类,因此大小将告诉您下一步该做什么。

    类数组的第二次删除表明为数组分配的内存是七个元素加上数组的大小(size_t)。操作员delete不知道数组的大小,也不知道该编译器提出的任何其他问题。因此,对于数组的手动内存分配,了解内存大小非常重要。

    第三次删除是基类,大小与第一次删除不同。

    全局算子delete对所有对象都是通用的,大小需要知道要释放多少。

    • 7

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5