to 令狐虫:有关你的auto_ptr的问题
不知道怎么回事,给你回的mail总是被退回来了,不得已只能在这说了:(
你的问题:
这几天在工作之余,下载了SGI STL来看。首先开刀的是auto_ptr(我觉得这个跟STL的其它部分联系不大,容易读懂,呵呵),但是还是碰到了一些疑问。但是CSDN最近似乎忙得很,登录都很困难,失望之余想到了您,希望您能帮助我。
我的问题是这样子的,我按自己的理解写了也一个smart_point类,其中大部分是是参照STL auto_ptr写的,但是有几个地方我觉得难以理解,所以按自己的想法做了些改动,我想知道,STL为什么那样做,我的类又有哪些缺陷呢?
1、auto_ptr::release()问题。这个函数我觉得很难理解,从代码上看,这个函数的作用是返回自身所指的内存的地址,然后【将自身指针指向空】,为什么要这样做呢?比如auto_ptr在其copy constructor里,就对内部的指针_point赋予了这样的值:__a.release()。这样一来,__a不是不能用了吗?我在我的版本里改用了get函数,这样会造成什么问题吗?还有,我的赋值运算符重载代码也是自己写过的,我的理解是:一旦一个指针p被赋了新值,那么它原来的值就会悬空从而造成泄露,所以我在每次赋值操作的时候将其旧值删除。但是这样会造成一个问题,就是两个指针指向同一块内存区的问题,隐约觉得这样的问题要用引用计数解决,可是不知道怎么写,因为这个操作似乎是对赋值运算符的右值操作(当它被赋给别人时,它的引用计数+1),重载运算符似乎也不能解决这个问题啊。至于STL的代码,我则又不理解了,它为什么用a.release()呢?这样右值的指针不是也失效了?
2、在STL里还定义了一个auto_ptr_ref结构,这个结构起到了什么用处?
3、还有一个问题我觉得奇怪。本来我想在main函数中写这样的代码的:smart_point<int> ptr1 = new int(6); 可是编译器(Borland C++ Builder 6/Command Line)给出了一个“ Cannot convert 'int *' to 'smart_point<int>'”的错误,我觉得奇怪,按我的理解,这样的写法,应该会调用ptr1(int *)构造函数,从而将内部指针_point指向申请出来的内存,可是为什么会错呢? smart_point<int> ptr1(new int(6));这样的写法就不错。难道是我的想法错了?
源码附后,希望cber先生能在百忙中给个回复。多谢。
令狐虫
2002/08/06
----------------------------------
template <class T>
class smart_point
{
public:
//Interface
explicit smart_point(T *p = NULL) : _point(p) {};
smart_point(smart_point &p) : _point(p.get()) {}; //注:STL的auto_ptr这里写的是p.release(),但现在还不理解这个release究竟干什么用。
~smart_point() { if (_point) delete _point; };
T& operator*() const
{ return *_point; };
T* operator->() const
{ return _point; };
smart_point& operator=(smart_point &p) //注:实现方法与STL有所不同,感觉STL的写法很难理解
{
if (p.get() != this->_point)
if (this->_point != NULL)
delete this->_point;
this->_point = p.get();
return *this;
};
smart_point& operator=(T *p)
{
if (p != this->_point)
if (this->_point != NULL)
delete this->_point;
this->_point = p;
return *this;
};
T* get()
{ return _point; };
private:
T *_point;
};
//------------------Main for Test--------------------
int main()
{
// int *p1 = new int(5);
// int *p2 = new int(6);
// smart_point<int> ptr1(p1);
// smart_point<int> ptr2(p2);
// smart_point<int> ptr1 = new int(5); //这个为什么会错?
// smart_point<int> ptr2 = new int(6);
smart_point<int> ptr1(new int(3));
smart_point<int> ptr2(new int(4));
smart_point<int> ptr3(ptr2);
cout << "*ptr1 = " << *ptr1 << endl;
cout << "*ptr2 = " << *ptr2 << endl;
cout << "*ptr3 = " << *ptr3 << endl;
ptr2 = ptr1;
cout << "*ptr1 = " << *ptr1 << endl;
cout << "*ptr2 = " << *ptr2 << endl;
return 0;
}
=========================================================================
我的回答:
其实对于ISO 14882(也就是大家所知道的C++标准文档)中的auto_ptr,很多人(包括国外的一些牛人)都觉得它的做法不是很好,目前在boost中对于smart pointer有几个不错的实现,你可以去参考一下它们的做法(boost源码可以从网上下载http://www.boost.org)
release()在copy ctor中的作用就是:保证一份memory只能有一个owner,如果你用get(),那么你的程序在对这两个owner做destroy动作时 ,会在第二次调用dtor时得到一个undefined的行为。引用计数的方式可以参见boost.share_ptr
auto_ptr_ref的问题,我现在记得不是很清楚了,需要翻翻书才行:(
smart_point<int> ptr1 = new int(6);编译出错的原因在这:
explicit smart_point(T *p = NULL) : _point(p) {};
因为你的ctor是explicit的,所以不能自动为你实现implicit conversion
因为最近对于C++的书籍几乎没有接触,所以第二个问题可能还是需要你自己去查书了,忘见谅
问题点数:1、回复次数:4Top
1 楼cber(cber)回复于 2002-08-08 15:37:17 得分 0
还没有来啊:(
拜托下次用一个可以收到回复的mail地址,这样我就不会搞得这么复杂了
算了,自己up一下,等你看完后结贴Top
2 楼anrxhzh(百宝箱)回复于 2002-08-08 17:58:44 得分 1
http://www.josuttis.com/libbook/auto_ptr.html
auto_ptr and auto_ptr_ref
This page contains details about the motivation of auto_ptr_ref as part of the auto_ptr class.
Top
3 楼anrxhzh(百宝箱)回复于 2002-08-08 18:38:23 得分 0
#include <memory>
std::auto_ptr<int> foo()
{
std::auto_ptr<int> __ap(new int);
return __ap;//1. ok, auto_ptr can copy const temporary
}
void foo2( std::auto_ptr<int> )
{
}
int main()
{
const std::auto_ptr<int> __cp = foo();
std::auto_ptr<int> __p = foo();
foo2( __p );//2. ok, auto_ptr can copy non const object
foo2( __cp );//3. error, auto_ptr can not copy const bject
}
auto_ptr_ref 是 auto_ptr 的实现细节,是一个诡计。如果不能够理解这个诡计也没有关系,只要明白为什么要使用这个诡计就可以了,这个诡计就是为了同时满足上例中的 1.2.3 。不幸的是,并不是所有的编译器都能够施展这个诡计的,比如VC6.0就不行,所以在VC6.0下使用auto_ptr的同志们可要多长个心眼呀。
Top
4 楼cber(cber)回复于 2002-08-11 12:58:46 得分 0
ft,最后up一次
再次对不能回复的mail地址表示不满Top




