zoukankan      html  css  js  c++  java
  • new delete/delete[] 测试

    测试代码:

    #include <iostream>
    
    using namespace std;
    
    class AA {
    public:
        AA(size_t count = 1)
        {
            _a = new int[count];
            cout<<"AA()"<<endl;
        }
        
        ~AA()
        {
            cout<<"~AA()"<<endl;
            delete[] _a;
            // cout<<"~AA()"<<endl;
        }
    
    private:
        int* _a;
    };
    
    int main() {
        char *str = new char[20];
        delete str;
        cout<<"0"<<endl;
    
    
        AA* p3 = new AA;         // 不报错,但未清理干净。p3的构造函数开辟的空间没有被释放
        free(p3);
        cout<<"1"<<endl;
        AA* p4 = new AA[10];   // dump
        AA* p5 = &p4[2];
        delete p4;
        cout<<"2"<<endl;
        AA* p5 = new AA;     // dump
        delete[] p5; 
        cout<<"3"<<endl;
    }

    似乎new/delete/delete[]的具体实现是和编译器相关的

    new的时候会额外申请4字节或更多字节的空间,存放元素个数,这样delete[]的时候,就知道要析构多少个元素。

    https://www.cnblogs.com/wkfvawl/p/10846851.html

    有的文档里说delete数组可以成功,但是在运行centos7 g++5.5编译的程序时会直接dump:

    *** Error in `./a.out': munmap_chunk(): invalid pointer: 0x0000000001fe7c48 ***

    但是对于没有显示析构函数的类或者内置变量,就能正常运行。

    new既是关键字也是操作符:

    newoperator new之间的联系:
    1)new表达式调用一个名为operator new(或者operator new[])的标准库函数。该函数分配一块足够大的、原始的、未命名的内存空间以便存储A类型的对象(或者对象数组);
    2)编译器运行相应地构造函数以构造这些对象,并为其传入初始值;
    3)对象被分配了空间并构造完成,返回一个指向该对象的指针
    事实上,如果类A重载了operator new,那么将调用A::operator new(size_t size),如果没有重载,就调用全局函数::operator new(size_t size),全局new操作符由c++默认提供。

    相关知识:

    1.如果你希望将对象产生于堆上,请使用new operator2.如果你只打算分配内存,请使用operator new,就不会调用构造函数。
    3.如果你打算在堆对象产生时自己决定内存分配方式,请自己重载operator new4.如果你打算在已分配的内存中构造对象,请使用placement new

    new和malloc

    operator new 从自由存储区上为对象动态分配内存空间,而 malloc 从堆上动态分配内存。
    事实上,我在网上看的很多博客,划分自由存储区与堆的分界线就是new/delete与malloc/free。然而,尽管C++标准没有要求,但很多编译器的new/delete都是以malloc/free为基础来实现的。那么请问:借以malloc实现的new,所申请的内存是在堆上还是在自由存储区上?
    
    从技术上来说,堆(heap)是C语言和操作系统的术语。堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,稍后调用free可把内存交还。
    而自由存储是C
    ++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为自由存储区。基本上,所有的C++编译器默认使用堆来实现自由存储,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,
    这时藉由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确。但程序员也可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。
    我们所需要记住的就是: 堆是操作系统维护的一块内存,而自由存储是C
    ++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价。

    在使用shared_ptr的时候,默认是不会delete[]数组(c++17开始才能传入数组类型: std::shared_ptr<int[]> p(new int[10]);),需要传入自定义的删除器:

    void myDelete (int *p)//自己的删除器,删除整型指针用的,当智能指针引用计数为0
    //就会自动调用来删除对象。
    {
        cout << "这里被调用了"<<endl;
        delete []p;
    }
    std::shared_ptr<int> p1(new int[5], deleter);

    p.s. C++标准规定:delete空指针是合法的,没有副作用。

  • 相关阅读:
    代码分层之模拟servlet调用dao
    Request对象和Response对象
    jquery-动画
    jquery-easyui
    phpcms
    Ajax做分页
    phpcms安装
    cms替换主页的步骤
    php 复习
    登录验证——————生成随机数
  • 原文地址:https://www.cnblogs.com/starRebel/p/14145100.html
Copyright © 2011-2022 走看看