BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #39019同步于 2010/5/8
CPP机器人发帖

[合集] 求助一个c++引用计数句柄的赋值操作符问题

jokerlee
2010/5/8镜像同步0 回复
☆─────────────────────────────────────☆ jkice (MeeMoo) 于 (Tue May 4 20:44:10 2010) 提到: 在看accelerated c++,第14章说引用计数句柄,这个类的赋值操作符定义如下: template <class T> Ref_handle<T>& Ref_handle<T>::operator=(const Ref_handle& rhs) { ++*rhs.refptr; if(--*refptr == 0) { delete refptr; delete p; } refptr = rhs.refptr; p = rhs.p; return *this; } 书上说通过先自增右操作数的引用计数,可以防止自我赋值,在C++ Primer也是这样说的,但是没有解释,我也没想明白,大家指教一下,谢谢 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Tue May 4 20:46:32 2010) 提到: 我也没明白你说什么。。。。 ☆─────────────────────────────────────☆ jkice (MeeMoo) 于 (Tue May 4 20:57:14 2010) 提到: 【 在 a206206 的大作中提到: 】 : 我也没明白你说什么。。。。 : -- : 黑暗凝集灵魂,堕落方能自由 : ................... 定义一个类,当指针用,当复制这个类的对象时,并不复制底层的数据,即可以有多个对象指向相同的底层数据。这个类有复制构造函数和重载赋值操作符,上面是重载的赋值操作符,其中refptr是个计数,记录的是指向这个底层数据的指针(就是这个类的对象)有多少个。书上说先给右操作数的计数加一可以防止自我赋值,这个我没懂。 呃。。。我觉得我还是没说明白。。。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Tue May 4 21:25:54 2010) 提到: 就是说比如a=a,是可以的,这时候指针计数器是1,但是自减了以后就是0,而他其实还有一个对象a,所以先自增就可以避免错误,如果是a=b,那么指向b类的尔计数器就躲一个,恩。 ☆─────────────────────────────────────☆ jkice (Bamboo) 于 (Tue May 4 21:31:45 2010) 提到: 【 在 a206206 的大作中提到: 】 : 就是说比如a=a,是可以的,这时候指针计数器是1,但是自减了以后就是0,而他其实还有一个对象a,所以先自增就可以避免错误,如果是a=b,那么指向b类的计数器就多一个,恩。 : -- : 黑暗凝集灵魂,堕落方能自由 : ................... 那a=a不是自我赋值吗? ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Tue May 4 21:33:59 2010) 提到: 【 在 jkice 的大作中提到: 】 : 那a=a不是自我赋值吗? 是啊,那是合法的操作啊 ☆─────────────────────────────────────☆ jkice (Bamboo) 于 (Tue May 4 21:46:18 2010) 提到: 【 在 a206206 的大作中提到: 】 : : 【 在 jkice 的大作中提到: 】 : : 那a=a不是自我赋值吗? : ................... 但是是要防止自我赋值,是不是我理解有问题,其他的赋值操作符都是通过*this != rhs来判断是不是自我赋值,要是是自我赋值就什么都不做,return *this,要是不是就先将左操作数的 数据成员delete掉,之后把右操作数赋给左操作数。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Tue May 4 22:34:55 2010) 提到: 为什么要防止,赋值确实会消除左值,但是因为他传的是this的一个拷贝,所以是可以的,但是如果有指针,就不能这么用了 ☆─────────────────────────────────────☆ Drust0101 (Drust.X) 于 (Thu May 6 12:32:51 2010) 提到: a=a时 ++*rhs.refptr; 加1 if(--*refptr == 0) 又减1, 所以没变,没有自我增值 再 refptr = rhs.refptr; 赋值没问题 如果先 refptr = rhs.refptr; 再 ++*rhs.refptr; ++refptr; 则a=a时refptr增加了,自我增值了,a=a时应该不增加引用计数 不知道理解的对不对。。。 ☆─────────────────────────────────────☆ jkice (Bamboo) 于 (Thu May 6 13:38:53 2010) 提到: 【 在 Drust0101 的大作中提到: 】 : a=a时 : ++*rhs.refptr; 加1 : if(--*refptr == 0) 又减1, : ................... 是不是说共享底层数据的赋值只和引用计数有关,赋值就是将引用计数加1,但是自我赋值不用加这个1,如果不是自我赋值,就看左操作数是不是最后一个指向底层数据的,如果是就先delete,之后在赋值,如果不是,就引用计数加1,再赋值。对吗? ☆─────────────────────────────────────☆ taps (Awesome) 于 (Thu May 6 14:00:30 2010) 提到: 1.无论怎样,左操作数-1和右操作数+1都是必要的操作。 2.这段代码强调的是用 “先将右操作数引用计数+1再将左操作数引用计数-1”,强调的是顺序,+1和-1都是必要操作,之所以有先后问题之存在于,-1的时候需要判断是否需要释放内存。如果某块内存只有一个引用计数指针指向它,那么对它的自我赋值,-1先执行将会删除内存。 【 在 jkice 的大作中提到: 】 : 是不是说共享底层数据的赋值只和引用计数有关,赋值就是将引用计数加1,但是自我赋值不用加这个1,如果不是自我赋值,就看左操作数是不是最后一个指向底层数据的,如果是就先delete,之后在赋值,如果不是,就引用计数加1,再赋值。对吗? ☆─────────────────────────────────────☆ jkice (Bamboo) 于 (Thu May 6 19:50:49 2010) 提到: 【 在 taps 的大作中提到: 】 : 1.无论怎样,左操作数-1和右操作数+1都是必要的操作。 : 2.这段代码强调的是用 “先将右操作数引用计数+1再将左操作数引用计数-1”,强调的是顺序,+1和-1都是必要操作,之所以有先后问题之存在于,-1的时候需要判断是否需要释放内存。如果某块内存只有一个引用计数指针指向它,那么对它的自我赋值,-1先执行将会删除内存。 : 【 在 jkice 的大作中提到: 】 : ................... 是不是这样,假设两个指针lhs和rhs,底层数据是data,当lhs!=rhs时,因为要将rhs赋给一个其他值,所以就需要将prt2的引用计数加1。之后检查左操作数是否是最后一个指向data的,要是是就先delete,之后再赋值。如果lhs==rhs,那么一加一减就没变,--*refptr就不可能为0,不为零就不会delete,只是后边的语句将lhs重新赋了自己的值,而引用计数没变,所以没有自我赋值。 ☆─────────────────────────────────────☆ taps (Awesome) 于 (Fri May 7 08:57:10 2010) 提到: 是的 【 在 jkice 的大作中提到: 】 : 是不是这样,假设两个指针lhs和rhs,底层数据是data,当lhs!=rhs时,因为要将rhs赋给一个其他值,所以就需要将prt2的引用计数加1。之后检查左操作数是否是最后一个指向data的,要是是就先delete,之后再赋值。如果lhs==rhs,那么一加一减就没变,--*refptr就不可能为0,不为零就不会delete,只是后边的语句将lhs重新赋了自己的值,而引用计数没变,所以没有自我赋值。
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。