malloc 和 free 都是 C/C++ 语言的标准库函数,new/delete 是 C++ 的运算符。
new 在底层调用malloc()和构造函数,delete 在编译器层面会调用对象的析构函数和free()。
Constructors are invoked when object initialization takes place.
在对象初始化时调用构造函数。
Destructors are called when an object goes out of scope or when a pointer to an object is deleted.
当对象超出作用域时或删除指向对象的指针时,会调用析构函数。
Thus, we can use the automatic destructor mechanism of objects to encapsulate raw pointers to manage dynamic memory.
由此,便可以利用对象的自动析构机制封装裸指针来管理动态内存。
#include class MyClass{private: int* p;public: MyClass() : p(new int(0)) { std::cout << "Created a pointer in default constructor." << '
'; } MyClass(int x) : p(new int(x)) { std::cout << "Created a pointer in overload constructor." << '
'; } ~MyClass() { delete p; std::cout << "Deleted a pointer in the destructor." << '
'; }};int main(){ { MyClass o; // constructor invoked here MyClass p(12);// constructor invoked here } // destructor invoked here(gets out of scope) MyClass *mc = new MyClass();// constructor invoked here delete mc; // o's destructor invoked getchar();} Here we allocate memory for a pointer in the constructor and deallocate the memory in the destructor. This style of resource allocation/deallocation is called RAII or Resource Acquisition is Initialization.
在这里,我们在构造函数中为指针分配内存,并在析构函数中释放内存。这种类型的资源分配/释放称为RAII,或者资源获取即初始化。
STL smart pointer is a generic template class that uses the automatic destruction mechanism of objects to encapsulate raw pointers to manage dynamic memory.
STL智能指针即是利用对象的自动析构机制封装裸指针来管理动态内存并实现了泛型的模板类。
A unique pointer called std::unique_ptr is a pointer that owns an object it points to. The pointer can not be copied. Unique pointer deletes the object and deallocates memory for it, once it goes out of scope.
名为std::unique_ptr的(动态内存资源)独享指针是拥有其指向的对象的指针。无法复制该指针。一旦对象超出范围,std::unique_ptr将删除该对象并为其释放内存。
// unique_ptr::operator= example#include #include int main () { std::unique_ptr foo; std::unique_ptr bar; foo = std::unique_ptr(new int (101)); // rvalue bar = std::move(foo); // using std::move std::cout << "foo: "; if(foo) std::cout << *foo << '
'; else std::cout << "empty
"; std::cout << "bar: "; if(bar) std::cout << *bar << '
'; else std::cout << "empty
"; return 0;}/* output:foo: emptybar: 101*/ 实现简单模拟:
#include templateclass Unique_ptr{T* m_ptr;public:Unique_ptr(T* ptr = nullptr):m_ptr(ptr){} ~Unique_ptr(){delete m_ptr;} // Copy constructor -- no copying allowed!Unique_ptr(const Unique_ptr& a) = delete; // Move constructor// Transfer ownership of a.m_ptr to m_ptrUnique_ptr(Unique_ptr&& a): m_ptr(a.m_ptr){a.m_ptr = nullptr;} // Copy assignment -- no copying allowed!Unique_ptr& operator=(const Unique_ptr& a) = delete; // Move assignment// Transfer ownership of a.m_ptr to m_ptrUnique_ptr& operator=(Unique_ptr&& a){// Self-assignment detectionif (&a == this)return *this; // Release any resource we're holdingdelete m_ptr; // Transfer ownership of a.m_ptr to m_ptrm_ptr = a.m_ptr;a.m_ptr = nullptr; return *this;} T& operator*() const { return *m_ptr; }T* operator->() const { return m_ptr; }bool isNull() const { return m_ptr == nullptr; }}; class Resource{public:Resource() { std::cout << "Resource acquired
"; }~Resource() { std::cout << "Resource destroyed
"; }}; int main(){Unique_ptr res1(new Resource);Unique_ptr res2; // Start as nullptr std::cout << "res1 is " << (res1.isNull() ? "null
" : "not null
");std::cout << "res2 is " << (res2.isNull() ? "null
" : "not null
"); //res2 = res1; // auto_ptr Resource* nudePtr(new Resource);// 裸指针delete nudePtr; //如果忘记delete,则nudePtr超出作用域时自动释放,// 释放的是自身,其指向的动态内存却再也没有机会释放,造成动态内存泄漏// res2超出作用域时会自动在栈上释放,同时会调用析构函数,delete m_ptr,释放堆上内存// 封装的指针(智能指针)在释放自身(栈)的同时释放了其成员指针指向的动态内存(堆内存)// 裸指针释放自身(栈)的同时却让其指向的动态内存失去了释放的机会(如果没有delete)// delete的不是nudePtr本身(本身超出作用域会自动在栈上释放),// delete针对的是其指向的堆内存,其实本质上也没有delete,只是标识为可重新链接的堆内存。return 0;}/*Resource acquired res1 is not null res2 is null Resource acquired Resource destroyed Resource destroyed */ We can have multiple pointers point to a single object. We can say that all of them own our pointed-to object, that is, our object has shared ownership. And only when last of those pointers get destroyed, our pointed to object gets deleted. This is what a shared pointer is for. Multiple pointers pointing to a single object, and when all of them get out of scope, the object gets destroyed. Shared pointers can be copied. This mechanism is implemented as std:shared_pt.
我们可以有多个指针指向单个对象。我们可以说他们都拥有我们的指向对象,也就是说,我们的对象拥有共享所有权。只有当最后一个指针被销毁时,我们的指向对象才会被删除。这就是共享指针的用途。多个指针指向单个对象,当所有指针都超出范围时,该对象就会被销毁。可以复制共享指针。这种机制在STL中实现为std:shared_pt。
#include #include using namespace std;void main(){shared_ptr pFirst( new int );//这时,只有pFirst这个指针指向这块int类型的内存,//所以这时的引用计數是1cout<<"当前引用计数:"< pCopy = pFirst;//因为pFirst和pCopy都指向这一块内存资源,//所以这一资泺的引用计教增加为2cout<<"当前引用计數:"< 实现简单模拟:
#include using namespace std;#define nullptr NULL// 智能指针shared_ptr的简单实现// 核心要理解引用计数,什么时候销毁底层指针,还有赋值、拷贝构造时候的引用计数的变化,// 析构的时候要判断底层指针的引用计数为0了才能真正释放底层指针的内存template class SmartPtr{ private: T *ptr; // 底层真实的指针 int *use_count; // 保存当前对象被多少指针引用计数 public: SmartPtr(T *p); // SmartPtr p(new int(2)); SmartPtr(const SmartPtr&orig); // SmartPtrq(p); SmartPtr&operator=(const SmartPtr &rhs); // q=p ~SmartPtr(); T operator*(); // 为了能把智能指针当成普通指针操作定义解引用操作 T*operator->(); // 定义取成员操作 T* operator+(int i); // 定义指针加一个常数 friend int operator-(SmartPtr&t1,SmartPtr&t2); // 定义两个指针相减 int getcount() { return *use_count; }};template int operator-(SmartPtr &t1, SmartPtr &t2){ return t1.ptr-t2.ptr;}template SmartPtr::SmartPtr(T *p){ ptr=p; try { use_count=new int(1); } catch (...) { delete ptr; // 申请失败释放真实指针和引用计数的内存 ptr= nullptr; delete use_count; use_count= nullptr; }}template SmartPtr::SmartPtr(const SmartPtr &orig) //复制构造函数{ use_count=orig.use_count;// 引用计数保存在一块内存,所有的SmarPtr 对象的引用计数都指向这里 this->ptr=orig.ptr; ++(*use_count); // 当前对象的引用计数加1}template SmartPtr& SmartPtr::operator=(const SmartPtr &rhs){ // 重载=运算符,例如SmartPtrp,q; p=q;这个语句中,首先给q 指向的对象的引用计数加1, // 因为p重新指向了q所指的对象,所以p需要先给原来的对象的引用计数减1, // 如果减一后为0,先释放掉p原来指向的内存,然后将q指向的对象的引用计数加1 后赋值给p ++*(rhs.use_count); if((--*(use_count))==0) { delete ptr; ptr= nullptr; delete use_count; use_count= nullptr; } ptr=rhs.ptr; *use_count=*(rhs.use_count); return *this;}template SmartPtr::~SmartPtr(){ getcount(); if(--(*use_count)==0) // SmartPtr 的对象会在其生命周期结束的时候调用其析构函数, // 在析构函数中检测当前对象的引用计数是不是只有正在结束生命周期的这个SmartPtr 引用, // 如果是,就释放掉,如果不是,就还有其他的SmartPtr 引用当前对象, // 就等待其他的SmartPtr对象在其生命周期结束的时候调用析构函数释放掉 { getcount(); delete ptr; ptr= nullptr; delete use_count; use_count=nullptr; cout<<"Free Dynamic memory resources"<T SmartPtr::operator*(){ return *ptr;}template T* SmartPtr::operator->(){ return ptr;}template T* SmartPtr::operator+(int i){ T *temp=ptr+i; return temp;}int main(){ { SmartPtr sptr(new int(5)); cout<< *sptr < -End-
| 留言与评论(共有 0 条评论) “” |