a smart pointer is an abstract data type that simulates a pointer while providing additional features, such as automatic garbage collection or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency. Smart pointers typically keep track of the objects they point to for the purpose of memory management. They may also be used to manage other resources, such as network connections and file handles.
很早之前就听说了smart pointer,也了解了个大概。 看完wikipedia上这段描述,还是没有真正理解smart pointer。这些描述比较虚,我们深入了解一些经典的smart pointer的原理,从而加深我们的理解。
1. std::auto_ptr
std::auto_ptr 属于 STL,当然在 namespace std 中,包含头文件 #include<memory> 便可以使用。std::auto_ptr 能够方便的管理单个堆内存对象。下面是一个使用的例子:
class PTR
{
public:
PTR(){cout<<
"
ctor
"<<endl;};
void doSomething(){cout<<
"
Do Something
"<<endl;};
~PTR(){cout<<
"
dector
"<<endl;};
};
void test_auto_ptr()
{
auto_ptr<PTR> ptr(
new PTR());
(ptr)->doSomething();
}
int _tmain(
int argc, _TCHAR* argv[])
{
test_auto_ptr();
return
0;
}
输出是:
ctor
Do Something
dector
Note: auto_ptr 利用了一个栈上的对象去管理一个堆上的对象。所以,在使用auto_ptr时一定要注意不要new一个auto_ptr,否则是达不到smart的目标的。
class PTR
{
public:
PTR(){cout<<
"
ctor
"<<endl;};
void doSomething(){cout<<
"
Do Something
"<<endl;};
~PTR(){cout<<
"
dector
"<<endl;};
};
void test_auto_ptr()
{
auto_ptr<PTR> *ptr =
new auto_ptr<PTR>(
new PTR());
(*ptr)->doSomething();
}
int _tmain(
int argc, _TCHAR* argv[])
{
test_auto_ptr();
return
0;
}
输出是:
ctor
Do Something
我们看到auto_ptr 似乎工作的挺好,那我们再看看下面的代码吧:
class PTR
{
public:
PTR(
int i){j=i;
cout<<
"
ctor
"<<endl;};
void doSomething(){cout<<
"
Do Something
"<<j<<endl;};
~PTR(){cout<<
"
dector
"<<endl;};
private:
int j;
};
void test_auto_ptr()
{
auto_ptr<PTR> ptr(
new PTR(
1));
auto_ptr<PTR> ptr2(
new PTR(
2));
ptr2 = ptr;
ptr2->doSomething();
ptr->doSomething();
(ptr)->doSomething();
}
int _tmain(
int argc, _TCHAR* argv[])
{
test_auto_ptr();
return
0;
}
输出是:
ctor
ctor
dector
Do Something1
然后就crash了。
原因在于ptr2 = ptr;这句话会剥夺ptr对原对象的所有权。VC中的代码实现如下所示:
_Myt&
operator=(_Myt& _Right) _THROW0()
{
//
assign compatible _Right (assume pointer)
reset(_Right.release());
//
in this case, ptr is _Right, after _Right.release(), _Right will become empty, the pointer held by _Right will be returnd by release() and become the input parameter of reset;
return (*
this);
}
_Ty *release() _THROW0()
{
//
return wrapped pointer and give up ownership
_Ty *_Tmp = _Myptr;
_Myptr =
0;
return (_Tmp);
}
void reset(_Ty *_Ptr =
0)
{
//
destroy designated object and store new pointer
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
}
我们看到了auto_ptr是有问题的,下面把它的问题列举一下吧,其实它已经是一个臭名昭著的smart pointer了:
1. 不可共享所有权,一个auto_ptr的实例对应到一个对象指针后,另外一个auto_ptr就不能再指向了,否则会被over delete,下面的函数在返回时就会crash,因为_ptr会被释放两次,上面的例子也可以说明这一点:
void test_auto_ptr()
{
PTR *_ptr =
new PTR(
1);
auto_ptr<PTR> ptr(_ptr);
auto_ptr<PTR> ptr2(_ptr);
//
ptr2 = ptr;
ptr2->doSomething();
ptr->doSomething();
(ptr)->doSomething();
}
2. std::auto_ptr 的 release() 函数只是让出内存所有权,并不会释放对象,具体实现可以看上面的代码;
3. std::auto_ptr 最好不要当成参数传递,为什么,给个例子?
在C++标准11中,std::unique_ptr用来取代auto_ptr。