关于vector转换为数组的讨论

dawndu 2005-04-29 08:23:53
实际编程中经常出现这样的情况:
比如说要使用画曲线的windows函数
BOOL Polyline(
HDC hdc, // handle to device context
CONST POINT *lppt, // pointer to array containing endpoints
int cPoints // number of points in the array
);
显然这个函数要传一个数组进去,我们可以从文件中读取点集到vector<POINT>中,那么现在就需要把vector转换为数组,一种方法当然是把vector拷贝到数组中,这个方法显然占用双倍的内存,可以舍弃。还有一种方法,如下:(PointList是vector<POINT>类型的)
const POINT *lpData=static_cast<POINT *>(PointList.begin());
这种方法可行否,在vc下是运行是没有问题的,但是显然这样比较怪
那么这种方法可行否,理论上如何讲?因为显然是将一个迭代器转型了。如果不行,有没有更好的方法?我想stl的设计人一定考虑过这些问题,因为这些应用是很普遍的

...全文
3394 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
xzygod 2005-04-30
  • 打赏
  • 举报
回复
不想用地址就不必用c/c++
dawndu 2005-04-30
  • 打赏
  • 举报
回复
to useresu(俗人)
不是不信,是看看有没有更好的高招,取地址看着觉得不是太安全
呵呵,你是不是等着冲星啊
yuhjnm_20001 2005-04-30
  • 打赏
  • 举报
回复
mark
bing_huo 2005-04-30
  • 打赏
  • 举报
回复
doSomething(&v[0], v.size());

这样就对了
useresu 2005-04-30
  • 打赏
  • 举报
回复
楼主,帖子还不结啊,
够详细了吧.

Scott Meyers这样的大师说的还不能信服?
dawndu 2005-04-30
  • 打赏
  • 举报
回复
哦,自己找到了
dawndu 2005-04-30
  • 打赏
  • 举报
回复
to bing_huo(我是一个演员!) :
只知道标准规定vector必须使用连续内存 并且保证顺序与vector一致
____________________________________________________________________________

没错,如果要做到知其然,知道这个足够了。但是vector毕竟不是c风格的数组,而是一个类,v[0]显然可以得到第一个元素,&v[0]就一定是第一个元素的地址吗?因为这个operator[]是重载了的,所以它做了什么我不看源码还真不知道,这个不知道标准有没有规定,请赐教!
当数据增加到某个时候,vector内部数组会内存再分配,因为c++没有像c那样的realloc这样的renew(这个是有原因的),所以内部数组的首地址甚至是会改变的.
还有Effective stl作者说的空vector的情况,所以,我觉得可能这个首地址显式的给出更好,就像string从实现上完全可以做到隐式给出到char *的转换,但是因为种种考虑还是用c_str显式给出一样。
我现在已经有了一种习惯,就是觉得c中的东西到c++中完全不一样。
比如在c中,做a=b;那么最后a就真的等于b了,但是在c++中,执行a=b,a就真的等于b吗?显然不见得。

ps:因为我平常都到vc版,觉得c++版都是作业贴,所以本人在c++版就一个裤衩,虽然说不上是高手,但是本人并不是菜鸟,这个也不是入门的作业贴。

to:useresu(俗人)
我只有一本英文的Effective STL,不知道你的中文版在哪里下的?
fireflyc 2005-04-30
  • 打赏
  • 举报
回复
vector<const POINT> lppt;
BOOL Polyline(hdc, &lppt[0], cPoints)

useresu 2005-04-30
  • 打赏
  • 举报
回复
楼主强人那,加分,大家继续讨论啊
bing_huo 2005-04-30
  • 打赏
  • 举报
回复
你认为就这么简单吗?你看过vector的源码吗?对于这个问题只是我看源码的时候想起来的,我只是想讨论一下而已。

老实说 源码没仔细读过 只知道标准规定vector必须使用连续内存 并且保证顺序与vector一致 这不就够了?

还有一点std::string 的c_str()是得到c风格字符数组 结尾要加'\0'的 这是特例 跟你说的 vector转数组又有什么关系? string的data()返回的才是一个真正的字符数组 无'\0'结尾~
dawndu 2005-04-30
  • 打赏
  • 举报
回复
你认为就这么简单吗?你看过vector的源码吗?对于这个问题只是我看源码的时候想起来的,我只是想讨论一下而已。
&v[0],如果不看源码,很难知道就是它内部那个数组的地址,比如说多继承的时候,你做static_cast转换,地址都是不一样的,lippman有本书讲的很好。
你们说的都是effective stl的Item 16
Item 16. Know how to pass vector and string data to legacy APIs.

Fortunately, it's easy. If you have a vector v and you need to get a pointer to the data in
v that can be viewed as an array, just use &v[0]. For a string s, the corresponding
incantation is simply s.c_str(). But read on. As the fine print in advertising often points
out, certain restrictions apply.
显然作者也认为c_str更simple
dawndu 2005-04-30
  • 打赏
  • 举报
回复
楼上说到哪里去了,偶又不是新手,这样显然不如string的.c_str考虑的优雅
bing_huo 2005-04-30
  • 打赏
  • 举报
回复
不是不信,是看看有没有更好的高招,取地址看着觉得不是太安全
呵呵,你是不是等着冲星啊


我晕 你不明白数组是什么东西? 把数组当参数传递还不是地址????
dawndu 2005-04-29
  • 打赏
  • 举报
回复
to :qhfu(崩溃)
我是要得到整个数组,不是一个元素
to:useresu(俗人)
你的说法很不错,呵呵

刚开始就有这么多回答,看来这个问题还是很普遍的,看有没有更好的办法,看string的.c_str这样的就很好,可惜vector没有
useresu 2005-04-29
  • 打赏
  • 举报
回复
呵呵,督促我自己学了些新东西,

谢谢楼主
useresu 2005-04-29
  • 打赏
  • 举报
回复
摘自effective stl
这样肯定没问题的,呵呵
大师说话,让人信服一些
useresu 2005-04-29
  • 打赏
  • 举报
回复
给定一个

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和g++中这么做的话,就会引发一个编译错误)

qhfu 2005-04-29
  • 打赏
  • 举报
回复
迭代器也重载了 ++
可以直接 it++;
useresu 2005-04-29
  • 打赏
  • 举报
回复
我觉的还是有问题,

只把迭代器传入就可以了吗?

记的effective stl中有这类问题的讨论,

可以参考一下
useresu 2005-04-29
  • 打赏
  • 举报
回复
const POINT *lpData=static_cast<POINT *>(PointList.begin());
这样转换只是把begin()迭代器转换成了Point指针啊,

后边的元素呢?
加载更多回复(2)

64,662

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧