auto_ptr
#include <iostream>
#include <memory>
using namespace std;
class A
{
private:
int _a;
public:
A(int a){ _a=a; }
void print(){ cout<<"A::print " << this->_a<<endl; }
};
int main()
{
std::auto_ptr<A>pa1(new A(1));
pa1->print();
cout<<"pa1 pointer: "<<pa1.get()<<endl;
std::auto_ptr<A>pa2(pa1); // copy constructor
pa2->print();
cout<<"pa1 pointer: "<<pa1.get()<<endl;
cout<<"pa2 pointer: "<<pa2.get()<<endl;
pa1->print();
return 0;
}
上面的代码运行的结果如下:
可以看到最后一个函数调用出现了错误,这是由于auto_ptr具有排他所有权导致的,因为上面的p1将自己对某个对象的所有权限让给了p2, 他就无法再访问只属于这个对象的内容了
但我代码给成这样,
class A
{
// private:
// int _a;
public:
// A(int a){ _a=a; }
void print(){ cout<<"A::print "<<endl; }
};
int main()
{
std::auto_ptr<A>pa1(new A());
pa1->print();
cout<<"pa1 pointer: "<<pa1.get()<<endl;
std::auto_ptr<A>pa2(pa1); // copy constructor
pa2->print();
cout<<"pa1 pointer: "<<pa1.get()<<endl;
cout<<"pa2 pointer: "<<pa2.get()<<endl;
pa1->print();
return 0;
}
上面的代码将类中的成员变量删除
运行结果:
可以看到上面的代码没有报错,原因是没有访问属于对象的成员变量,这个类也没有成员变量,而成员函数是所有对象共享的。
unique_ptr
替换了auto_ptr,不再允许将对象赋值、拷贝给另外一个对象
int main()
{
unique_ptr<string> upt(new string("sbsb"));
unique_ptr<string> upt1(upt);
return 0;
}
如下,不再允许拷贝、赋值
如上图也可以看到编译器是如何禁用拷贝和赋值的
就是再函数后面 加delete
shared_ptr
一句话解释:多个指针可以指向同一个对象,每多添加一个指针指向这个对象,该对象的count变量就++, 当count==0时,释放该对象
解决了auto_ptr 某个对象仅能由一个指针拥有的情况
class A
{
private:
int _a;
public:
A(int a){ _a=a; }
void print(){ cout<<"A::print "<<this->_a<<endl; }
};
int main()
{
shared_ptr<A>sp1(new A(1));
sp1->print();
cout<<"sp1 pointer:"<<sp1.get()<<endl;
shared_ptr<A>sp2(sp1); // copy constructor
sp2->print();
cout<<"sp1 pointer: "<<sp1.get()<<endl;
cout<<"sp2 pointer: "<<sp2.get()<<endl;
cout<<"count sp1:"<<sp1.use_count()<<endl;
cout<<"count sp2:"<<sp2.use_count()<<endl;
return 0;
}
运行结果:
weak_ptr
是一种不控制对象声明周期的智能指针,其设计的目的是为了配合shared_ptr的工作,它只能从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。
weak_ptr用于解决shared_ptr相互引用时的死锁问题
#include <iostream>
#include <memory>
using namespace std;
class B;
class A
{
public:
shared_ptr<B> pb_;
~A() { cout<<"~A()"<<endl; }
};
class B
{
public:
shared_ptr<A> pa_;
~B() { cout<<"~B()"<<endl; }
};
void fun()
{
shared_ptr<B> pb(new B());
shared_ptr<A> pa(new A());
pb->pa_ = pa;
pa->pb_ = pb;
cout<<pb.use_count()<<endl;
cout<<pa.use_count()<<endl;
}
int main()
{
fun();
return 0;
}
程序执行结果:
如图所示:两个智能指针的引用计数都为2,因为pb指向自己创建的对象,同时自己也被pa中的pb_指向, pa同理
当退出函数fun时,两个对象都调用析构函数,使其自身的引用计数--,但还是1,这时就造成了资源浪费
解决:将其中一个改为weak_ptr
因为资源B的引用计数值一直为1,当调用析构函数时,B的计数变为0,B释放的同时也会使A的计数减一。同时pa析构时使A的计数减一
那么A的计数为0,A得到释放
share_ptr 实现
(2条消息) C++面试题(四)——智能指针的原理和实现_算法的天空-优快云博客_智能指针实现
template <typename T>
class SmartPointer {
public:
//构造函数
SmartPointer(T* p=0): _ptr(p), _reference_count(new size_t){
if(p)
*_reference_count = 1;
else
*_reference_count = 0;
}
//拷贝构造函数
SmartPointer(const SmartPointer& src) {
if(this!=&src) {
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
}
}
//重载赋值操作符
SmartPointer& operator=(const SmartPointer& src) {
if(_ptr==src._ptr) {
return *this;
}
releaseCount();
_ptr = src._ptr;
_reference_count = src._reference_count;
(*_reference_count)++;
return *this;
}
//重载操作符
T& operator*() {
if(ptr) {
return *_ptr;
}
//throw exception
}
//重载操作符
T* operator->() {
if(ptr) {
return _ptr;
}
//throw exception
}
//析构函数
~SmartPointer() {
if (--(*_reference_count) == 0) {
delete _ptr;
delete _reference_count;
}
}
private:
T *_ptr;
size_t *_reference_count;
void releaseCount() {
if(_ptr) {
(*_reference_count)--;
if((*_reference_count)==0) {
delete _ptr;
delete _reference_count;
}
}
}
};
int main()
{
SmartPointer<char> cp1(new char('a'));
SmartPointer<char> cp2(cp1);
SmartPointer<char> cp3;
cp3 = cp2;
cp3 = cp1;
cp3 = cp3;
SmartPointer<char> cp4(new char('b'));
cp3 = cp4;
}