const auto_ptr保证拥有权不能转移的实现原理?

力为
博客专家认证
2005-10-24 09:56:42
在《C++标准程序库》p55,提到了auto_ptr使用了一个技巧,能够copy和复制non-const auto_ptr,但不可以copy和复制const atuo_ptr。

但我看了好几遍,就是看不懂。请明白的给指点一下:), 有分相送哦。
...全文
357 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
xlsue 2005-11-27
  • 打赏
  • 举报
回复
//刚写了个类似的程序,表明临时对象可以转型,const对象却不可以,因为没有相应的const转型函数
#include <iostream>
class x
{
public:
operator int() { return 1; }
};

void f(x& x1) { }
void f(int i) { }
int main()
{
//const x x1;
//f(x1);
f(x());

getchar();

return 0;
}
xlsue 2005-11-06
  • 打赏
  • 举报
回复
回复人: xzgyb(老达摩) ( ) 信誉:110 2005-10-31 10:27:00 得分: 0


我没看过<<C++标准程序库>>

xlsue(小林饼子):

a.
auto_ptr<int> a1(auto_ptr<int)());
这个是函数的声明
返回类型auto_ptr<int>
参数类型auto_ptr<int>(*)()
-----------------------------------------------------------------------
一言惊醒梦中人.very good! 这时才回想到Meyers说的...已经想通了:)
xzgyb 2005-10-31
  • 打赏
  • 举报
回复
我没看过<<C++标准程序库>>

xlsue(小林饼子):

a.
auto_ptr<int> a1(auto_ptr<int)());
这个是函数的声明
返回类型auto_ptr<int>
参数类型auto_ptr<int>(*)()
fiftymetre 2005-10-31
  • 打赏
  • 举报
回复

回复人: xlsue(小林饼子) ( ) 信誉:100


你狠,还能留点话,让偶也吱一下呢:(
力为 2005-10-31
  • 打赏
  • 举报
回复
大家一起来解决啊
xlsue 2005-10-29
  • 打赏
  • 举报
回复
const auto_ptr是不能修改的.能调用它的只有3个const函数.构造函数和析构函数例外.
我一直对这个问题搞不懂:
(a):
auto_ptr<int> a1(auto_ptr<int)()); //正确.可是参数是临时变量啊.是const auto_ptr<int>.
(b):
const auto_ptr<int> a2(new int(10));
auto_ptr<int> a3(a2); //不正确.这是当然的
难道书中说的是要区分这两个?
(a)似乎通过某些优化什么?
-------------------------------------------------------------------------------------------------------
#include <iostream>
//#include <memory>
#include <cstdio>

template<typename _Tp1>
struct auto_ptr_ref
{
_Tp1* _M_ptr;

explicit
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
};

template<typename _Tp>
class auto_ptr
{
private:
_Tp* _M_ptr;

public:
typedef _Tp element_type;

explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p)
{
std::cout << "以一个new出来的指针构造auto_ptr" << std::endl;
}

auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release())
{
std::cout << "copy constructor by called." << std::endl;
}


template<typename _Tp1>
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release())
{
std::cout << "member auto_ptr constructor" << std::endl;
}

auto_ptr&
operator=(auto_ptr& __a) throw()
{
reset(__a.release());
return *this;
}


template<typename _Tp1>
auto_ptr&
operator=(auto_ptr<_Tp1>& __a) throw()
{
reset(__a.release());
return *this;
}

~auto_ptr() { delete _M_ptr; }


element_type&
operator*() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return *_M_ptr;
}

element_type*
operator->() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return _M_ptr;
}

element_type*
get() const throw() { return _M_ptr; }


element_type*
release() throw()
{
element_type* __tmp = _M_ptr;
_M_ptr = 0;
return __tmp;
}


void
reset(element_type* __p = 0) throw()
{
if (__p != _M_ptr)
{
delete _M_ptr;
_M_ptr = __p;
}
}


auto_ptr(auto_ptr_ref<element_type> __ref) throw()
: _M_ptr(__ref._M_ptr) { }

auto_ptr&
operator=(auto_ptr_ref<element_type> __ref) throw()
{
if (__ref._M_ptr != this->get())
{
delete _M_ptr;
_M_ptr = __ref._M_ptr;
}
return *this;
}

template<typename _Tp1>
operator auto_ptr_ref<_Tp1>() throw()
{
std::cout << "call auto_ptr_ref" << std::endl;
return auto_ptr_ref<_Tp1>(this->release());
}

template<typename _Tp1>
operator auto_ptr<_Tp1>() throw()
{
std::cout << "转型" << std::endl;
return auto_ptr<_Tp1>(this->release());
}

};

int main()
{
::auto_ptr<int> a(::auto_ptr<int>());

getchar();

return 0;
}

xlsue 2005-10-28
  • 打赏
  • 举报
回复
目前觉得温柔说的有道理.我先慢慢琢磨琢磨.如果有什么发现再驳倒他:)
昨天和家人吵架了,近来不能经常上网了...
力为 2005-10-28
  • 打赏
  • 举报
回复
如:
const auto_ptr<int> a1(new int);
auto_ptr<int> a2(a1); //a1为nonconst value, a2为 const value,能调用匹配的nonconst函数.
--------------------
如果上面成立的话, a1的拥有权岂不是给了a2。const就没有用了。

xlsue 2005-10-27
  • 打赏
  • 举报
回复
我的回答有问题.等下重新整理好后再来回答你的问题...
xlsue 2005-10-27
  • 打赏
  • 举报
回复
const atuo_ptr根本就不能调用
template<typename _Tp1>
operator auto_ptr_ref<_Tp1>() throw()
{ return auto_ptr_ref<_Tp1>(this->release()); }
完成转型。const对象不能调用nonconst成员函数。
纠正一下."const atuo_ptr根本就不能调用"这句错了.因为const是右值.如果是左值得才不能调用非const函数.如:
const auto_ptr<int> a1(new int);
auto_ptr<int> a2(a1); //a1为nonconst value, a2为 const value,能调用匹配的nonconst函数.
-------------------------------------------------------------------------------
const auto_ptr在
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }报错了,把一个常量auto_ptr传进去,修改常量对象会报错...
力为 2005-10-27
  • 打赏
  • 举报
回复
to xlsue(小林饼子) :
按照你的解释,const atuo_ptr岂不是可以交出拥有权?那就不对了吧。

const atuo_ptr根本就不能调用
template<typename _Tp1>
operator auto_ptr_ref<_Tp1>() throw()
{ return auto_ptr_ref<_Tp1>(this->release()); }
完成转型。const对象不能调用nonconst成员函数。

引入auto_ptr_ref主要是解决右值的问题。

右值是const的,但又能调用nonconst,这个地方我不太明白。
请指点。
ddmor 2005-10-25
  • 打赏
  • 举报
回复
需要明白常对象不能使用非常函数。因为auto_ptr中有__a.release()是非常函数(因为它会释放资源,改变成员变量),所以必须要使用非常量的对象。因此不能对常对象进行操作
xlsue 2005-10-25
  • 打赏
  • 举报
回复
哦!我知道了,那是温柔的解释。我的理解和他有点不同:
先上源码:
//auto_ptr的源码:
template<typename _Tp1>
struct auto_ptr_ref
{
_Tp1* _M_ptr;

explicit
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
};


template<typename _Tp>
class auto_ptr
{
private:
_Tp* _M_ptr;

public:
typedef _Tp element_type;

explicit
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }

template<typename _Tp1>
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }

auto_ptr&
operator=(auto_ptr& __a) throw()
{
reset(__a.release());
return *this;
}

template<typename _Tp1>
auto_ptr&
operator=(auto_ptr<_Tp1>& __a) throw()
{
reset(__a.release());
return *this;
}

~auto_ptr() { delete _M_ptr; }

element_type&
operator*() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return *_M_ptr;
}

element_type*
operator->() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return _M_ptr;
}

element_type*
get() const throw() { return _M_ptr; }

element_type*
release() throw()
{
element_type* __tmp = _M_ptr;
_M_ptr = 0;
return __tmp;
}

void
reset(element_type* __p = 0) throw()
{
if (__p != _M_ptr)
{
delete _M_ptr;
_M_ptr = __p;
}
}

auto_ptr(auto_ptr_ref<element_type> __ref) throw()
: _M_ptr(__ref._M_ptr) { }

auto_ptr&
operator=(auto_ptr_ref<element_type> __ref) throw()
{
if (__ref._M_ptr != this->get())
{
delete _M_ptr;
_M_ptr = __ref._M_ptr;
}
return *this;
}

template<typename _Tp1>
operator auto_ptr_ref<_Tp1>() throw()
{ return auto_ptr_ref<_Tp1>(this->release()); }

template<typename _Tp1>
operator auto_ptr<_Tp1>() throw()
{ return auto_ptr<_Tp1>(this->release()); }
};

---------------------------------------------------------------------------------------------------------------------------
要理解三个东西:
1.引数推导
2.重载
3.隐式转型

auto_ptr型别可以通过,不再废话。
现在说const auto_ptr 和 auto_ptr&型别。
以copy构造为例:
先看: auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
由于这个函数的参数为引用型别。因此,呼叫这个函数的时候,型别不能为const auto_ptr和auto_ptr的引用,它们无法退化为正常型别。我们知道,const是不可以修改的,因此编译器报错。而对于引用型别调用型别,参数无法退化,引用-->一般型别,不匹配。于是编译器寻找是否有其他的重载函数更加匹配?编译器终于发现-->
template<typename _Tp1>
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
只要经过:
template<typename _Tp1>
operator auto_ptr_ref<_Tp1>() throw()
{ return auto_ptr_ref<_Tp1>(this->release()); }
就可以转型为:
struct auto_ptr_ref
{
_Tp1* _M_ptr;

explicit
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
};
于是编译器就这么做了,然后调用完成控制权的转移:
struct auto_ptr_ref
{
_Tp1* _M_ptr;

explicit
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
};




xlsue 2005-10-25
  • 打赏
  • 举报
回复
你的那话没有前文和后文。。。
力为 2005-10-25
  • 打赏
  • 举报
回复
"由于non-const引用不能绑定到右值,所以也就不能让auto_ptr 从一个temporary object生成."
这句话如何理解?
xlsue 2005-10-24
  • 打赏
  • 举报
回复
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
注意这里是引用,把const 和 引用过滤掉了。。。
xlsue 2005-10-24
  • 打赏
  • 举报
回复
http://community.csdn.net/Expert/topic/4255/4255787.xml?temp=.2993891

64,439

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧