分享
 
 
 

C++中的auto_ptr

王朝c/c++·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

stl <memory> 文件中的 std::auto_ptr 在C++中的故事特别多, 在它的演变过程中至少出现了3个版本.

http://www.josuttis.com/libbook/auto_ptr.html 这个连接里面有它完整的故事.

VC6中STL带的auto_ptr( 带owner字段)的版本应该就是文中说的Version 2.

最新的Version里面包含了一个auto_ptr_ref, 这个是当将auto_ptr作为函数返回值和函数参数时需要引入的

一个"额外间接层".

下面是它的一些说明:

auto_ptr的拷贝构造函数和一般我们常见的不同, 它的参数rhs并不是const reference, 而是refence,

auto_ptr( /*const */ auto_ptr& rhs)

{

...

}

假设我们需要将一个auto_ptr作为某个函数的返回值, 例如

auto_ptr<int> source()

{

return auto_ptr<int>(new int(3));

}

那么我们如何在caller中得到返回的结果呢?

理所当然的语法是:

auto_ptr<int> p( source() ); (拷贝构造函数)

或者

auto_ptr<int> p = source(); (拷贝构造函数)

或者

auto_ptr<int> p = ...; (operator=)

p = source();

但是如果没有auto_ptr_ref的存在, 上面这些行实际上应该是一个编译错误(VC6不报错), 原因是:

C++中有左值/右值之分, 函数如果返回值, 那么是r-value. 右值作为reference函数参数时, 只能是const reference.

因此source函数返回的auto_ptr作为rhs实参调用auto_ptr的拷贝构造函数时, 只能是const refernce, 但是

这个函数的签名需要rhs为reference, 因此无法编译.

举个最简单的例子:

有函数:

int foo() { return 0; }

void bar(int & i) { }

调用

int& i = foo() ; //错误

const int& i = foo(); //OK

bar(foo()) //错误

同理, 拷贝构造函数不过是一个特殊的"函数"而已, 我们上面的source函数返回的auto_ptr对象也只能作为一个

const auto_ptr&, 但是这个拷贝构造函数需要的参数原型是auto_ptr&, 而不是const auto_ptr& .

因此auto_ptr引入了一个'额外的间接层' auto_ptr_ref, 来完成一个从r-value到l-value之间的过渡.

基本的思路是;

提供另外一个构造函数, 接受一个以值传递的auto_ptr_ref:

auto_ptr( auto_ptr_ref ref)

{

....

}

然后在auto_ptr类中, 提供一个自动转型的函数

operator auto_ptr_ref ()

{

.....

}

这样, source返回一个auto_ptr, 编译器尝试调用拷贝构造函数, 发现参数不必配(期望const), 然后发现了一个自动转型的

operator auto_ptr_ref()函数, 而后又发现通过调用该自动转型得到一个auto_ptr_ref对象后, 可以调用caller的

auto_ptr的以auto_ptr_ref为参数的非explicit的构造函数, 完成了一个auto_ptr到另外一个auto_ptr之间的复制过程.

注意一点: operator auto_ptr_ref () 不是const成员函数.

std::auto_ptr在很多情况下是很便利的, 例如一个函数内部需要通过new分配一个结构, 那么谁来释放是一个问题,

一种原则是谁分配, 谁释放, 但是对于这种情况显然不合适.

利用auto_ptr就简单得多了: 谁拥有谁释放, 谁都不要那么就编译器自动释放它. 例如

有个函数:

auto_ptr<sth> create_sth()

{

auto_ptr<sth> p(new sth);

return p;

}

调用1:

auto_ptr<sth> p = create_sth();

...

p退出作用域, 自动释放.

调用2:

create_sth();

没有人接受这个返回的对象, 那么编译器自动会调用auto_ptr的析构函数释放之.

sink也是一个作用:

例如我已经拥有一个auto_ptr<sth>对象的指针, 那么我可以定义一个sink函数, 原型如下:

void sink(auto_ptr<sth> p)

{

}

正如sink名字暗示的一样, sink函数起到一个吸收作用, 将某个外部的auto_ptr对象吸收过来,类似于宇宙中的"黑洞".

例如:

auto_ptr<sth> p(new sth);

sink(p);

//这里, p指向null了, p所指的sth对象已经被sink函数"吸收"了.

当然为了防止这种情况在你不注意的情况下发生, 你可以

const auto_ptr<sth> p(new sth);

sink(p); //编译错误

auto_ptr<sth> p2 = p; //编译错误

这样, 一个const auto_ptr<sth>的对象一旦构造完成, 永远不会失去对该对象的拥有权. "一旦拥有, 从不失去".

当然auto_ptr最重要的作用, 也是它的原始目的是为了提供异常安全.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有