《C++标准程序库》里的auto_ptr的“转型操作”
作者的代码在这里 :
http://www.josuttis.com/libbook/util/autoptr.hpp.html
C++标准程序库》的page 55,以及原文page 54 都提到了conversions(转型操作):
中文:
//
auto_ptr的剩余部分的内容(auot_ptr_ref以及相关函数)设计非常精致的技巧,使得我们能够拷贝和赋值non-const aut_ptr,但是不能拷贝和赋值const auto_ptr .这里面有两个要求:1) 必须将auto_ptr作为右值传递到函数中,或者有函数中返回,而auto_ptr是class,所以这里必须由构造函数完成 2)拷贝auto_ptr的时候,原指针必须放弃拥有全,所以也就需要修改原本的auto_ptr.
一般的构造函数当然可以拷贝右值,但是为了这点,必须把参数类型声明为reference to const object 。如果在auto_ptr中使用一般的copy构造函数,则我们必须将auto_ptr内部的指针定义为mutable。只有这样,才能在auto_ptr的构造函数中修改它.
//
英文:
//
The rest of the class auto.ptr (auxiliary type auto_ptr_ref and functions using it) consists of rather tricky conversions that enable you to use copy and assignment operations for nonconstant auto_ptrs but not for constant auto_ptrs (see page 44 for details). The following is a quick
explanation. We have the following two requirements:
1. It should be possible to pass auto_ptrs to and from functions as rvalues. Because auto_ptr is a class, this must be done using a constructor.
2. When an auto_ptr is copied, it is important that the source pointer gives up ownership. This requires that the copy modifies the source auto_ptr.
An ordinary copy constructor can copy an rvalue, but to do so it must declare its parameter as a reference to a const object. To use an ordinary constructor to copy an auto_ptr we would have to declare the data member containing the real pointer mutable so that it could be modified in the copy constructor. But this would allow you to write code that copies auto_ptr objects that were actually declared const, transferring their ownership in contradiction to their constant status.
//
问题:
1)拷贝构造函数里面的参数如作者说的,“必须为reference to const object”吗?
看我的程序!
2)如果不是,正如我程序中一样,没有了auto_ptr_ref的帮助,也照样可以实现“我们能拷贝和赋值none-const auto_ptr”,不能拷贝和赋只“const auto_ptr”!那么auto_ptr_ref还有必要么? 我哪儿考虑错了?
附我的程序:
#include <iostream>
using namespace std;
template <class _Tp> class auto_ptr {
private:
_Tp* _M_ptr;
public:
explicit auto_ptr(_Tp* __p = 0): _M_ptr(__p) {}
auto_ptr(auto_ptr& __a) : _M_ptr(__a.release()) {}
auto_ptr& operator=(auto_ptr& __a){
if (&__a != this) {
delete _M_ptr;
_M_ptr = __a.release();
}
return *this;
}
_Tp& operator*() const {
return *_M_ptr;
}
_Tp* release() {
_Tp* __tmp = _M_ptr;
_M_ptr = 0;
return __tmp;
}
~auto_ptr() { delete _M_ptr; }
};
class Helper
{
public:
Helper()
{
cout<<"Helper()"<<endl;
}
Helper(const Helper& t)
{
cout<<"Helper::Cotr"<<endl;
}
void say()
{
cout<<"Helper::say()"<<endl;
}
};
int main()
{
auto_ptr<Helper> p1(new Helper);
(*p1).say();
auto_ptr<Helper> p2(p1);
(*p2).say();
const auto_ptr<Helper> p3(new Helper);
auto_ptr<Helper> p4(p3); // wrong!
(*p3).say() ;
cin.get();
}