兔子的技术博客

兔子

   :: 首页 :: 联系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新评论

阅读排行榜

评论排行榜

转自:http://dev.csdn.net/article/17/17508.shtm
(只转了一部分)

因为 C++语言已经于1998年被标准化,C++的中坚分子在努力推动程序员从数组转到vector时就没什么顾虑了。同样显然的情况也发生于尝试使开发者从char*指针迁移到string对象的过程中。有很好的理由来做这些转变,包括可以消除常见的编程错误(参见条款13),而且有机会获得STL算法的全部强大能力(比如参见条款31)。

但是,障碍还是有的,最常见的一个就是已经存在的传统C风格的API接受的是数组和char*指针,而不是vector和string对象。这样的API函数还将会存在很长时间,如果我们要高效使用STL的话,就必须和它们和平共处。

幸运的是,这很容易。如果你有一个vector对象v,而你需要得到一个指向v中数据的指针,以使得它可以被当作一个数组,只要使用&v[0]就可以了。对于string对象s,相应的咒语是简单的s.c_str()。但是是只读的。如广告中难懂的条文时常指出的,必然会有几个限制。

给定一个

vector<int> v;
表达式v[0]生产一个指向vector中第一个元素的引用,所以,&v[0]是指向那个首元素的指针。vector中的元素被C++标准限定为存储在连续内存中,就像是一个数组,所以,如果我们想要传递v给这样的C风格的API:
void doSomething(const int* pInts, size_t numInts);

我们可以这么做:

doSomething(&v[0], v.size());

也许吧。可能吧。唯一的问题就是,如果v是空的。如果这样的话,v.size()是0,而&v[0]试图产生一个指向根本就不存在的东西的指针。这不是件好事。其结果未定义。一个较安全的方法是这样:


if (!v.empty()) {
 doSomething(
&v[0], v.size());
}

如果走错路了,你可能会碰到一些半吊子的人物,他们会告诉你说可以用v.begin()代替&v[0],因为(这些讨厌的家伙将会告诉你)begin返回指向vector内部的迭代器,而对于vector,其迭代器实际上是指针。那经常是正确的,但正如条款50所说,并不总是如此,你不该依赖于此。begin的返回类型是iterator,而不是一个指针,当你需要一个指向vector内部数据的指针时绝不该使用begin。如果你基于某些原因决定键入v.begin(),就应该键入&*v.begin(),因为这将会产生和&v[0]相同的指针,这样可以让你有更多的打字机会而且让其他要弄懂你代码得人感觉到更晦涩。坦白地说,如果你正在和告诉你使用v.begin()代替&v[0]的人打交道的话,你该重新考虑一下你的社交圈了。(译注:在VC6中,如果用v.begin()代替&v[0],编译器不会说什么,但在VC7和GCC中这么做的话,就会引发一个编译错误)

类似从vector上获取指向内部数据的指针的方法,对string不是可靠的,因为(1)string中的数据并没有承诺被存储在连续内存中,(2)string的内部表示形式并没承诺以一个null字符结束。这解释了string的成员函数c_str存在的原因,它返回一个按C风格设计指针,指向string的值。因此我们可以这样传递一个string对象s给这个函数,

。。。。。。。。。。。
。。。。。。。。。

posted on 2009-11-19 16:19 会飞的兔子 阅读(306) 评论(0)  编辑 收藏 引用 所属分类: C++库,组件

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