c++11新特性引入完善了智能指针,来动态管理内存,可自动释放内存,避免了内存泄漏和悬挂指针的问题,方便资源管理。
头文件 :
#include <memory>
类名 | 描述 |
unique_ptr | 独占所指向的对象,同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现) |
shared_ptr | 可以共享对象,计数 |
weak_ptr | 配合 shared_ptr 来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少. |
auto_ptr | 已废弃 |
unique_ptr
unique_ptr,独占智能指针,提供对动态分配的单一对象所有权的管理。因为独占所指向对象,所以同一时刻只有一个实例。其指向给定的内存资源,不能被拷贝,不能值传递,只能移动语义和右值引用允许其在所有权转移时高效地进行转移。当其被销毁时可自动释放所管理的资源。
unique_ptr的使用
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Test
{
public:
Test() {
cout << "Test()" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
void Output()const {
cout << "Output()" << endl;
}
};
unique_ptr<string> fun(const string& str)
{
return make_unique<string>(str);
}
int main() {
unique_ptr<int> u1 = make_unique<int>(10);
unique_ptr<int> u2(new int(20));
cout<<"*u1="<< *u1 << endl;
cout<<"*u2="<< *u2 << endl;
unique_ptr<int> u3 = move(u1); // 移动语义,u1的内存释放,u1的内存交给u3管理
cout<<"u1.get()="<<u1.get()<<endl; //输出为nullptr
cout<<"u3.get()="<<u3.get()<<endl;
cout<<"*u3="<<*u3<<endl;
unique_ptr<string> u4 = fun("hello world!");
cout << *u4 << endl;
unique_ptr<Test> u5 = make_unique<Test>();
unique_ptr<Test> u6(new Test);
u5->Output();
u6->Output();
unique_ptr<int[]> u7(new int[5]);
for (int i = 0; i < 5; ++i) {
u7[i] = i ;
}
for (int i = 0; i < 5; ++i) {
cout<<u7[i]<<" ";
}
cout<<endl;
return 0;
}
unique_ptr的实现
template <class T>
class UniquePtr
{
public:
UniquePtr(T* ptr) {
this->ptr = ptr;
}
~UniquePtr() {
if (ptr != nullptr)delete ptr;
}
T& operator*() {
return *ptr;
}
T* get() {
return ptr;
}
T* operator->() {
return ptr;
}
private:
UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr&) = delete;
private:
T* ptr;
};
shared_ptr
允许多个智能指针共享同一块内存资源。内部使用引用计数来跟踪对象被共享地次数,当计数为0时,资源被释放。提供更灵活地内存共享,但可能存在循环引用地问题。
shared_ptr的使用
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class B;
class A
{
public:
A() { cout << "A::A() called " << endl; }
~A() { cout << "~A::~A() called " << endl; }
shared_ptr<B>p;
//weak_ptr<B>p; //加入weak_ptr可避免引用成环
};
class B
{
public:
B() { cout << "B::B() called " << endl; }
~B() { cout << "~B::~B() called " << endl; }
//shared_ptr<A>p;
//weak_ptr<A>p;
};
int main() {
shared_ptr<int>s1 = make_shared<int>(10);
//shared_ptr<int>s1(new int(10)); //new表达式作为构造函数参数,其效率低。多使用 make_shared
shared_ptr<int>s2(s1); //拷贝构造
shared_ptr<int>s3=s2; //重载
cout << "*s1="<< *s1 <<",s1.use_count()=" << s1.use_count() << ",s1.get()" << s1.get() << endl;
cout << "*s2="<< *s2 <<",s2.use_count()=" << s2.use_count() << ",s2.get()" << s2.get() << endl;
cout << "*s3="<< *s3 <<",s3.use_count()=" << s3.use_count() << ",s3.get()" << s3.get() << endl;
//关于引用成环的问题
shared_ptr<A> pA(new A);
shared_ptr<B> pB(new B);
//下面两句导致了A与B的循环引用,结果就是A和B对象都不会析构
pA->p = pB;
pB->p = pA;
cout << "pA use_count:" << pA.use_count() << endl;
cout << "pB use_count:" << pB.use_count() << endl;
return 0;
}
shared_ptr的实现
template <class T>
class SharedPtr {
public:
SharedPtr() : ptr(nullptr), cnt(nullptr) {
}
SharedPtr(T *p) : ptr(p), cnt(nullptr) {
if (ptr) {
cnt = new int(1);
}
}
SharedPtr(SharedPtr &other) : SharedPtr() {
ref(other);
}
~SharedPtr() {
unRef();
}
int use_count() const {
if (cnt) return *cnt;
return 0;
}
T &operator*() {
return *ptr;
}
const T &operator*() const {
return *ptr;
}
T *operator->() {
return ptr;
}
const T *operator->() const {
return ptr;
}
SharedPtr &operator=(SharedPtr &other) {
unRef();
ref(other);
return *this;
}
private:
void ref(SharedPtr &other) {
if (other.ptr) {
ptr = other.ptr;
cnt = other.cnt;
++(*cnt);
}
}
void unRef() {
if (cnt) {
--(*cnt);
if (*cnt == 0) {
delete ptr;
delete cnt;
}
}
}
private:
T *ptr;
int *cnt;
};
weak_ptr
用于解决共享指针可能导致的循环引用问题。
可从共享指针创建,但不会增加引用计数,不会影响资源的释放。
通过weak_ptr::lock()可以获取一个共享指针来访问资源。
weak_ptr实例化
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class B;
class A
{
public:
A() { cout << "A::A() called " << endl; }
~A() { cout << "~A::~A() called " << endl; }
shared_ptr<B>p;
//weak_ptr<B>p; //加入weak_ptr可避免引用成环
};
class B
{
public:
B() { cout << "B::B() called " << endl; }
~B() { cout << "~B::~B() called " << endl; }
//shared_ptr<A>p;
//weak_ptr<A>p;
};
weak_ptr<A>get() {
shared_ptr<A>p1(new A);
return p1;
}
int main() {
weak_ptr<A> p2 = get();
shared_ptr<A> P3 = p2.lock();
cout << P3 << endl;
if (P3) {
cout << "对象可用" << endl;
}
else
{
cout << "对象不可用" << endl;
}
return 0;
}