C++—— 数组名与向量名

首先说一下自己的理解,然后参考理解

1、数组名代表数组的第一个元素的首地址

2、向量名代表这个容器的名字,&向量名表示这个容器的首地址

3、当拷贝给相同类型的其他变量时,采用值拷贝,即* 地址传值;

实例:

数组:

向量:

以下转自:

http://www.cnblogs.com/chhuach2005/p/3627011.html

https://blog.csdn.net/fao9001/article/details/75006369

 

1.问题的提出

        在没有了解vector之前,动态数组一般都是又new创建的。在了解vector后发现vector竟是那样方便好用,但方便的同时却是以牺牲执行效率为代价的。网上对vector和array的评价和吐槽,也是喜忧参半,各有不同啊。在面临选择的时候,我们到底用哪一种呢,我们可能都犹豫过?下面对该问题进行理论分析和实际测试验证。

2.理论分析

 

2.1预备知识-程序的内存分配

       一个由C/C++编译的程序占用的内存分为以下几个部分
       1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。是一种线性结构,其操作方式类似于数据结构中的栈,操作速度较快。但程序员是无法控制。
       2 、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,是一种链式结构,分配方式倒是类似于链表,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
        3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
        4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
        5、程序代码区—存放函数体的二进制代码。

        其中栈和堆构成了动态数据区:


├———————┤低端内存区域 
│ …… │ 
├———————┤ 
│ 动态数据区 │ 
├———————┤ 
│ …… │ 
├———————┤ 
│ 代码区 │ 
├———————┤ 
│ 静态数据区 │ 
├———————┤ 
│ …… │ 
├———————┤高端内存区域 

       以上堆和栈的分析参考博客1,关于堆和栈的区别与联系更详细的分析,请点击博客1

2.2数组、动态数组和vector的讨论如下:

       回到本文的主题,数组是底层数据类型,存放在栈中,其内存的分配和释放完全由系统自动完成,效率最高;动态数组是程序员由new运算符创建的,存放在堆中,需由delete运算符人工释放,否则会内存泄露;vector,存放在堆中,由STL库中程序负责内存的分配和释放,使用方便。

        关于vector的分析,参考STL源码剖析(P119-vector的内存管理)和C++primer(第四版9.4vector容器的自增长),vector的构造和内存管理如图1所示。如果容器中已经没有空间容纳新的元素,此时,由于元素必须连续存储以便索引访问,所以不能在内存中随便找个地方存储这个新元素。于是,vector 必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间中的元素被复制到新存储空间里,接着插入新元素,最后撤销旧的存储空间。这是vector效率低的主要原因。

        注意所谓的动态自增加,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。注意size和capacity的区别,size指容器当前拥有的元素个数,capacity指容器在必须分配新存储空间之前可以存储的元素总数,capacity总是大于或等于size的。

                                                  图1(来自STL源码剖析,图4-2)

3.数组、动态数组、vector的测试

       对vector、预先reverse的vector、数组、new创建的动态数组测试代码如下:

       vector的测试代码:

[cpp] view plaincopyprint?

  1. DWORD start=GetTickCount();  
  2. int t=100;  
  3. int n=200000;  
  4. while (t)  
  5. {  
  6.     vector<int> a,b;  
  7.     for (int i=0;i<n;i++)  
  8.         a.push_back(i);  
  9.     t--;  
  10. }  
  11. cout<<"Runing time of program:"<<GetTickCount()-start<<endl;  

        预先reverse的vector的测试代码:

[cpp] view plaincopyprint?

  1. start=GetTickCount();  
  2. t=100;  
  3. n=200000;  
  4. while (t)  
  5. {  
  6.  vector<int> a,b;  
  7.  b.reserve(n+1);  
  8.  for (int i=0;i<n;i++)  
  9.      b.push_back(i);  
  10.  t--;  
  11. }  
  12. cout<<"Runing time of program:"<<GetTickCount()-start<<endl;  


        数组的测试代码:

[cpp] view plaincopyprint?

  1. start=GetTickCount();  
  2. t=100;  
  3. n=200000;  
  4. while (t)  
  5. {  
  6.  int  a[200000];  
  7.  for (int i=0;i<n;i++)  
  8.     a[i]=i;  
  9.  t--;  
  10. }  
  11. cout<<"Runing time of program:"<<GetTickCount()-start<<endl;  


         new创建的动态数组:

[cpp] view plaincopyprint?

  1. start=GetTickCount();  
  2. t=100;  
  3. n=200000;  
  4. while (t)  
  5. {  
  6.  int  *p=new int[n+1];  
  7.  for (int i=0;i<n;i++)  
  8.      p[i]=i;  
  9.  delete []p;  
  10.      t--;  
  11. }  
  12. cout<<"Runing time of program:"<<GetTickCount()-start<<endl;  


       运行结果为:

       运行结果从上到下依次为,vector,预先reverse的vector、数组和动态数组的以上代码的执行时间(单位ms),从中可以看出,数组的执行效率是vector的10倍左右。执行效率不在同一个数量级,虽然容器操作简单方便。其效率排序依次是数组>动态数组>预先reverse的vector>vector。总之,数组和容器各有千秋,若硬件速度够快,对时间要求不那么高,用容器方便,也未尝不可。关键看你,看中什么,是效率还是方便。

c++使用 vector指针访问vector元素时,不能简单的类似于c中数组和指针的方式。需要使用迭代器。

 

int main()

{

vector<int> s;

vector<int> *p = &s;

s.push_back(1);

for (vector<int>::iterator it = p->begin(); it != p->end(); it++)

cout << *it<<endl; //使用迭代器,正确

 

cout << p[0] << endl; //错误

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值