测试代码:
#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既是关键字也是操作符:
new 和 operator 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 operator。 2.如果你只打算分配内存,请使用operator new,就不会调用构造函数。 3.如果你打算在堆对象产生时自己决定内存分配方式,请自己重载operator new。 4.如果你打算在已分配的内存中构造对象,请使用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空指针是合法的,没有副作用。