金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
用 (*it).m 还是 it->m

摘自《Extended STL》

标准库要求,所有值类型为聚合类型的迭代器必须支持指针成员选取运算符(operator ->()),下面是使用该运算符的示例代码:

struct X
{
  int x;
};

some_iterator<X>  si  = . . .
some_iterator<X>  si2 = . . .
some_iterator<X>  end = . . .

if( end != si &&
    end != si2)
{
  si->x = si2->x;
}

标准(C++-03: 24.1.1;1)要求,对一个迭代器应用指针成员选取运算符,在语义上等同于先对其应用解引用运算符,再应用点号成员选取运算符,即it->m与(*it).m等效。

可惜,使用该运算符会遇上麻烦。

假设我们有一个容器类型C,它的实例保存智能指针类型P的实例,P用于管理对象生存期。P上定义了一个release()方法用于提早释放对象。进一步假设,被P管理的类型T上也定义了一个release()方法。在下面代码片断中,我们希望通过该容器的迭代器类型I的一个实例,调用T::release()方法:

C   cont = . . .
I   it   = cont.begin();
it->release();

不幸的是,这段代码调用的不是T::release()方法,它调用的是P::release()方法,从而销毁了T的实例。当我们再次使用cont这个容器的时候,就可能遇到各种奇怪的问题,以下代码才是真正实现我们想法的代码:

C   cont = . . .
I   it   = cont.begin();
it->->release();                                                          

可是C++并不支持这样的语句,且理由充分。(想象一下,如果C++支持这样的语句,"模糊C++代码"大赛上,会有多少参赛代码,争着在一条语句中塞进最多的operator->()调用!)

为使C++满足我们的想法,我们必须放弃成员选取运算符而转用解引用运算符,就像以下代码示例中一样:

C   cont = . . .
I   it   = cont.begin();
(*it)->release();                                                         

这是迭代器语法中恼人的小缺点。

在迭代器中支持指针成员选取运算符,没什么实质的意义,而仅仅是语法糖。我认为标准中将这规定为迭代器概念的一个特性是严重的错误。在我的日常工作中,除了仅有几个特例外,我完全避免使用迭代器的指针成员选取运算符,而使用解引用和点号成员选取运算符。我建议你也这么做。

Tip: Prefer iterator dereference and the dot member selection operator ((*it).m) over the pointer member selection operator (it->m).

提示: 使用解引用及点号成员选择运算符((*it).m)代替指针成员选择运算符(it->m)。

(转载请注明来源于金庆的专栏)
posted on 2008-04-24 10:16 金庆 阅读(1947) 评论(5)  编辑 收藏 引用 所属分类: 1. C/C++

评论

# re: 用 (*it).m 还是 it->m[未登录] 2008-04-24 11:57 heroboy
it.operator->()->operator->()->Release();
所以,boost里面专门做个一个放指针的容器  回复  更多评论
  

# re: 用 (*it).m 还是 it->m 2008-04-24 17:11 王晓轩
的确是语法糖,为了使迭代器更形似指针而设的吧~~  回复  更多评论
  

# re: 用 (*it).m 还是 it->m 2008-05-06 09:11 不懂
我更希望是容器释放指针
cont.delete(it);  回复  更多评论
  

# re: 用 (*it).m 还是 it->m 2008-05-18 04:54
it->->release(); 这种用法很好么?
(*it)->release(); 这种用法恼人么?
楼主犯昏了吧....  回复  更多评论
  

# re: 用 (*it).m 还是 it->m[未登录] 2008-08-27 11:13 raof01
(*it).m;
it->m;

(*it)->m;
相同吗?  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理