VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1372|回复: 15

关于C++中vector数组的首地址问题

[复制链接]
Syc 发表于 2017-8-21 14:39:30 | 显示全部楼层 |阅读模式
近期的几个项目用到了C++标准模板库STL中的vector容器,即:动态数组,感觉也挺方便好用,跟MFC中的CArray不相上下,而且还跨平台,还是非常不错的。当前的几个项目都是用VS2013编译开发的,用着 vector 也都不错的。我举个小例子:

  1. #include "stdafx.h"
  2. #include <vector>
  3. using namespace std;

  4. int main(int argc, char **argv)
  5. {
  6.         vector <int> arr_ints;
  7.         for (int idx = 0; idx < 100; ++idx)
  8.         {
  9.                 arr_ints.push_back(idx);
  10.         }

  11.         return 0;
  12. }
复制代码


这个例子很简单,就是先定义一个 vector 动态数组,成员的类型是 int 整型,之后用个 for 循环把 100个数字放到动态数组 arr_ints 中,如此而已。
接下来呢,比如有个函数 add_value,其功能就是对指定的数组内部元素的值+1,第一个参数 pArrInts 传递的是 int 型数组的首地址,第二个参数 nArrLen 传递的是数组的大小,代码如下:
  1. void add_value(int *pArrInts, int nArrLen)
  2. {
  3.         if (!pArrInts || nArrLen <= 0) return;
  4.         for (int idx = 0; idx < nArrLen; ++idx)
  5.         {
  6.                 pArrInts[idx] += 1;
  7.         }
  8. }
复制代码


下面呢,我想调用函数 add_value,参数传递刚刚在 main 函数中定义的动态数组 arr_ints。我直接在 main 函数中这样调用肯定不行:add_value(arr_ints, arr_ints.size()); 编译都不通过。第二个参数是 arr_ints.size(),即vector动态数组的大小,这个没问题。那么第一个参数呢,add_value 想要的是数组的首地址,你直接传递 arr_ints 肯定是不行了,普通的数组:int arr_name[10]; 的名字 arr_name 可以代表数组的首地址,但是 vector 不行,他是一个对象,不是首地址。

于是我就找啊找,找到了 vector 提供了 data() 成员函数,使用它就可以了,直接返回数组内部成员的首地址,如果 vector 为空,即没有成员节点的话,那么 data() 返回 NULL,所以函数的调用改成如下就可以了:
add_value(arr_ints.data(), arr_ints.size()); 一点问题没有。

在以后的项目中我也一直使用 data() 方法来得到 vector 内部的数组的首地址。但最近有个朋友的项目要使用vs2008来开发编译,期间呢就遇到了个问题。这里面还以上面的代码为例,在 vs2008中编译呢就直接报错了,说 data() 方法不是 vector 的成员函数,说 arr_ints 对象引用不了 data() 方法。哎呀。。。怪了,之前的代码在 vs2013 上面一点问题没有,怎么到 vs2008 中就犯病了呢。忽然想到是不是 C++11 标准的事儿,因为 vs2013 本身开始全面支持 C++11,vs2008肯定不支持了。于是到网上一查,确实是这么回事:
http://en.cppreference.com/w/cpp/container/vector/data
vector 的 data 方法是在C++11中才被支持的。所以vs2008肯定用不了了。问题就来了,我就是要得到 vector 中数组元素的首地址该怎么办呢?

到网上又是百度,又是谷歌。。。还真是找到了点方法提供给大家。
vector 他本身是动态数组,所以也肯定是数组,那么内存模型就要遵循数组的形式,不然就犯规了。所以其内存空间必定是连续的。所以数组的首地址也就是数组中第1个元素的地址,也就是数组中索引为0的元素的地址。有了这个保证动态数组 arr_ints 的首地址也就是:&arr_ints[0] 对吧?我们来调试代码验证一下:
  1. int main(int argc, char **argv)
  2. {
  3.         vector <int> arr_ints;
  4.         for (int idx = 0; idx < 100; ++idx)
  5.         {
  6.                 arr_ints.push_back(idx);
  7.         }

  8.         int *p_data_1 = arr_ints.data();
  9.         int *p_data_2 = &arr_ints[0];

  10.         add_value(arr_ints.data(), arr_ints.size());

  11.         return 0;
  12. }
复制代码


没错,p_data_1 和 p_data_2 的值是相等的,也验证了我们的想法。所以,我们也可以这样调用 add_value 函数:add_value(&arr_ints[0], arr_ints.size()); 结果也是没问题的。

知道了原理之后,获得 vector 动态数组的首地址总共有以下几种写法:
  1. int *p_data_1 = arr_ints.data();
  2. int *p_data_2 = &arr_ints[0];
  3. int *p_data_3 = &arr_ints.at(0);
  4. int *p_data_4 = &arr_ints.front();
复制代码


有个问题要注意下,不能使用:
int *p_data_5 = arr_ints.begin(); 编译不通过,另外 begin 返回的迭代器,不是元素的地址,所以肯定不行,但是可以这样做:
  1. int *p_data_6 = &*arr_ints.begin();
复制代码
就可以啦!

总结一下,获得 vector 动态数组的内部元素首地址总共有 6 种方法,其中第 5 种是错误的,所以还剩下 5 种:

  1. int *p_data_1 = arr_ints.data();
  2. int *p_data_2 = &arr_ints[0];
  3. int *p_data_3 = &arr_ints.at(0);
  4. int *p_data_4 = &arr_ints.front();
  5. int *p_data_6 = &*arr_ints.begin();
复制代码


下面再给大家说下获取首地址问题的注意点及危险性,这个大家一定要看仔细了,以后用的时候也要多加注意(回复后可见):

游客,如果您要查看本帖隐藏内容请回复

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

2017666 发表于 2017-8-21 16:55:19 | 显示全部楼层
学习一下虽然 看着很模糊

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

nsky567 发表于 2017-8-21 17:59:03 | 显示全部楼层
感谢老大感谢老大感谢老大感谢老大

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

eagle1103 发表于 2017-8-21 19:22:49 | 显示全部楼层
感谢老大

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

koolit 发表于 2017-8-22 00:16:18 来自手机 | 显示全部楼层
又增知识了

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

koolit 发表于 2017-8-22 00:16:35 来自手机 | 显示全部楼层
又增知识了

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

angeltony 发表于 2017-8-22 11:30:11 | 显示全部楼层
感谢老大感谢老大感谢老大感谢老大

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

68ui 发表于 2017-8-22 11:38:33 | 显示全部楼层
如果您要查看本帖隐藏内容请回复

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

Mtong 发表于 2017-8-22 15:59:52 | 显示全部楼层
学习一下

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

woliveyou 发表于 2017-8-22 19:36:34 | 显示全部楼层

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

huangyushun 发表于 2017-8-28 17:31:59 | 显示全部楼层
学习一下动态数组

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

gaoyeshun 发表于 2017-8-31 08:58:02 | 显示全部楼层
楼主讲的实在是太好了。

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

VC松 发表于 2017-9-2 10:02:16 | 显示全部楼层
谢谢分享!

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

bzd 发表于 2017-9-6 11:17:53 | 显示全部楼层
快快快快快快给我看

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

harecn 发表于 2017-9-22 20:39:22 | 显示全部楼层
多谢 老大分享     

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友,一个好办法就是给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入驿站

本版积分规则

展开

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )

返回顶部
x

VC驿站微信公众号cctry2009

GMT+8, 2017-10-21 23:38

Powered by Discuz!

© 2009-2017 cctry.com

快速回复 返回顶部 返回列表