Chinaunix首页 | 论坛 | 博客
  • 博客访问: 413519
  • 博文数量: 168
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-09 13:46
文章分类

全部博文(168)

文章存档

2015年(51)

2014年(30)

2013年(87)

我的朋友

分类: C/C++

2013-10-11 11:05:03

原文地址:C++之vector内存在分配 作者:scq2099yt

一、通用容器大小操作
        所有容器类型都提供4种与容器大小相关的操作,包括:
        (1)c.size():返回容器c中的元素个数
        (2)c.max_size():返回容器c可容纳的最多元素个数,返回类型为c::size_type
        (3)c.empty():返回标记容器大小是否为0的布尔值
        (4)c.resize(n):调整容器c的长度大小,使其能容纳n个元素,如果n         (5)c.resize(n, t):调整容器c的大小,使其容纳n个元素,所有新添加的元素值都为t
        容器类型提供resize操作来改变容器所包含的元素个数。如果当前的容器长度大于新的长度值,则该容器后部的元素会被删除;如果当前的容器长度小于新的长度值,则系统会在该容器后部添加新元素:
        vector ivector(10, 42);    //10 ints: each has value 42
        ivector.resize(15);                   //adds 5 elements of value 0 to back of ivector
        ivector.resize(25, -1);              //adds 10 elements of value -1 to back of ivector
        ivector.resize(5);                     //erases 20 elements from the back of ivector
        resize操作可带有一个可选的元素值形参。如果在调用该函数时提供了这个参数,则所有新添加的元素都初始化为这个值。如果没有这个参数,则新添加的元素采用值初始化。
        需要注意的是:resize操作可能会使迭代器失效,对于所有的容器类型,如果resize操作压缩了容器,则指向已删除的元素的迭代器失效。

二、vector容器的自增长
        为了支持快速的随机访问,vector容器的元素以连续的方式存放——每一个元素都紧挨着前一个元素存储。
        已知元素是连续存储的,当我们在容器内添加一个元素时,如果容器中已经没有空间容纳新的元素,此时,由于元素必须连续存储以便索引访问,所以不能在内存中随便找个地方存储这个新元素,于是,vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素,存放在旧存储空间中的元素被复制到新存储空间里,接着插入新元素,最后撤销旧的存储空间。
        需要注意的是:如果vector容器在每次添加新元素时,都要这么分配和撤销内存空间,其性能将会非常慢,简直无法接受。
        vector的优势在于:以最小的代价连续存储元素,由此而带来的访问元素的便利弥补了其存储代价。
        为了使vector容器实现快速的内存分配,其是实际分配的容量要比当前所需的空间多一些。vector容器预留了这些额外的存储区,用于存放新添加的元素。于是,不必为每个新元素重新分配容器。所分配的额外内存容量的确切数目因库的实现不同而不同。比起每添加一个新元素就必须重新分配一次容器,这个分配策略带来显著的效率。事实上,其性能非常好,因此在实际应用中,比起list和deque容器,vector的增长效率通常会更高。
        vector提供了两个成员函数:capacity和reserve,使程序员可与vector容器内存分配的实现部分交互工作。capacity操作获取容器能够存储的元素总数
,而reserve操作则告诉vector容器应该预留多少个元素的存储空间。
        弄清楚容器的capacity(容量)和size(长度)的区别非常重要,size指容器当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。默认情况下,创建完vector后,其size和capacity都为0,但是向vector插入元素后,会发生变化,通常capacity会比size大,比如:
        vector ivec;
        for (vector::size_type ix=0; ix!=24; ++ix)
        {
            ivec.push_back(ix);
        }
        cout << "ivec: size: " << ivec.size()
                << " capacity: " << ivec.capacity() << endl;
        上面代码输出结果如下:
        ivec: size: 24 capacity: 32
        当然,你也可以用reserve来为vector预留额外的存储空间:
        ivec.capacity(50);
        cout << "ivec: size: " << ivec.size()
                << " capacity: " << ivec.capacity() << endl;
        该操作只改变了容器的capacity,而不改变size大小,则其输出如下:
        ivec: size: 24 capacity: 50
        如果将预留的容量用完,又当如何:
        while (ivec.szie() != ivec.capacity())

        {
            ivec.push_back(0);
        }
        cout << "ivec: size: " << ivec.size()
                << " capacity: " << ivec.capacity() << endl;
        只要有剩余容量,vector就不会做任何内存分配或重新分配的工作,直至耗尽了所有预留的容量,则其输出如下:
        
ivec: size: 50 capacity: 50
        如果此时再添加新元素,则vector必须为自己重新分配内存空间:
        ivec.push_back(51);
        
cout << "ivec: size: " << ivec.size()
                << " capacity: " << ivec.capacity() << endl;
        当vector不得不分配新的存储空间时,会以加倍当前容量的分配策略(具体策略与库的实现相关)实现重新分配,则其输出结果如下:
        
ivec: size: 51 capacity: 100
        此外,每种实现都要遵循以下原则:确保push_back操作高效地在vector中添加元素。从技术上来说,在原来为空的vector容器上n次调用push_back函数,从而创建拥有n个元素的vector容器,其执行时间永远不能超过n的常量陪。

        

        
        
阅读(847) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~