auto_ptr的copying函数的一点思考

先说点题外话。

在C++中,有两个行为:

  • 如果某函数接受的参数不是期待的类型,编译器会尝试进行隐式的转换。将传入参数进行适配,使得函数调用能够成功
  • 这样的隐式的转换只能进行一次。编译器不可能先将TypeA隐式转换为TypeB,接着又把TypeB隐式转换为TypeC

下面一段代码验证了这两个行为:

1 struct A
 2 {
 3     int _m; 
 4     A():_m(0){};
 5 };
 6 
 7 struct B
 8 {
 9     A _m; 
10     int _alias;
11     B(A a):_m(a),_alias(0){};
12 };
13 
14 struct C
15 {
16     B _m; 
17     C(B b):_m(b){};
18 };
19 
20 struct D
21 {
22     C _m; 
23     D(C c):_m(c){};
24 };
25 
26 A a;
27 B b(a);
28 C c1(b), c2(a), c3 = C(a);
29 // C c4 = a;
30 // D d1(a);
31 D d2(b);

对象a、b和c1创建时没有隐式转换。

对象c2和c3创建时,编译器将参数a隐式转换为一个临时的TypeB对象;d2创建时,编译器将参数b隐式转换为一二临时的TypeC对象。

对象c4不能被创建,因为编译器并不负责两次隐式转换(TypeA–>TypeB–>TypeC);同样d1也不能创建同样是因为需要两次隐式转换(TypeA->TypeB->TypeC)。

另外,copying函数指的是拷贝构造函数和赋值函数。


今天看《C++标准程序库:自修教程与参考手册》中关于auto_ptr的部分,提到它的copying函数只能用auto_ptr作参数,不能用普通指针。请看一下代码所表现的:

1 #include <memory> 
 2 using namespace std;
 3 
 4 class A
 5 {
 6 };
 7 
 8 auto_ptr<A> pa(new A); 
 9 auto_ptr<A> pb = pa; 
10 auto_ptr<A> pc = auto_ptr<A>(new A); 
11 // auto_ptr<A> pd = new A;

pb和pc可以被auto_ptr正确赋值,而pd不能被普通指针A*赋值。

这里涉及到的问题有两个:

  • 为何要规定这种行为
  • 内部是如何去实现的

第一个问题比较明了,因为auto_ptr中有“资源所有权”的问题,每时每刻,某一个资源(比如一块内存神马的)只能属于一个auto_ptr,因此在它的copying函数实现中,必定会包含有资源所有权转移的代码。而普通指针并没有所有权的概念,当然不能被作为copying函数的参数。这种行为肯定是应该禁止的。

而要回答第二个问题,请先看看本文开头描述的两种行为中的第一种,按说,在auto_ptr_copying中的pd被赋值时,new A应该可以由编译器隐式转换为anto_ptr类型的,怎么就失败了呢! 打开auto_ptr定义所在stl中的memory文件,源码是这样的:

1 template<typename _Tp>
 2     class auto_ptr
 3     {
 4     private:
 5       _Tp* _M_ptr;
 6       
 7     public:
 8       /// The pointed-to type.
 9       typedef _Tp element_type;
10       
11       /**
12        *  @brief  An %auto_ptr is usually constructed from a raw pointer.
13        *  @param  p  A pointer (defaults to NULL).
14        *
15        *  This object now @e owns the object pointed to by @a p.
16        */
17       explicit
18       auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
19 
20       // other source code 
21       // ......
22     }

注意第17行上的修饰构造函数的explicit关键字,它规定auto_ptr的构造函数不能参与隐式转换(在隐式转换时禁止调用),只能显式进行转换,因此在auto_ptr_copying中没有隐式转换。问题貌似到此已经清楚了。

那么,如果不计后果地把这个explicit给去掉呢?是不是就可以进行隐式转换了?结果是否定的。

auto_ptr的copying函数大有玄机,回头看看本文开头描述的两种行为中的第二种,再结合这篇专门讲述auto_ptr_ref的文章,应该就豁然开朗了!
原文链接: https://www.cnblogs.com/springlie/archive/2012/11/14/auto_ptr-copying-member-func.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/69438

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午1:48
下一篇 2023年2月9日 下午1:48

相关推荐