Effective STL:13 - 18 vector 和 string

来源:互联网 发布:ios 两个数组相同元素 编辑:程序博客网 时间:2024/06/05 14:27

所有STL容器都是有用的,但大多数C++程序员会发现使用vector和string的时候更多一些。设计vector和string的目的就是为了代替在大多数应用中使用的数组。


13. vector和string优先于动态分配的数组。

每当发现需要动态分配一个数组时(如想写new T[……]时),都应该考虑用vector 和string来代替。因为vector和string自己管理内存。


14.使用reserve来避免不必要的内存分配。

STL容器内存增加的流程:

1.分配一块大小为当前容量某个倍数的新内存,在大多数实现中,vector和string的容量每次都以2的倍数增长。

2.把容器所有元素从旧的内存拷贝到新的内存中。

3.析构掉旧内存中的对象。

4.释放旧内存。


每当这些步骤发生的时候,vector和string中所有的指针,迭代器和引用都将变得无效。


避免重新内存分配的关键在于尽早的使用reserve,最好是容器刚被构造出来之后就使用reserve。

如下面代码所示:在循环过程中,内存不会发生重新分配。

vector<int> v;v.reserve(1000);for(int i = 1; i <= 1000; ++i)v.push_back(i);

或者下面的代码, push_back()不会使string的迭代器,指针和引用无效。

string s;……if(s.size() < s.capacity())s.push_back('x');

总之,两种解决方法,若能切确知道或者大致估计容器最终会有多少元素,可以使用reverse,第二种方法是先预留足够大的空间, 当把所有数据都加入以后,在去除多余的容量。


15.注意string实现的多样性。

实现string的方法非常的多。


16.了解如何把vector和string数据传给旧的API。

旧的C API还存在,它们使用数组和char*指针来进行数据交换而不是vector或者string对象。


解决方法:如果有一个vector v,需要得到一个指向v中数据的指针,直接使用&v[0],而对于string s,则对应的形式是s.c_str()。


&v[0]是指向第一个元素的指针。如有这样的一个函数接口:

void doSomething(const int* pInts,size_t numInts)


则我们可以这样调用:

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


此外,不要用begin()去代替指针。因为begin()返回的是迭代器,但是迭代器不一定是指针。



而如果采用s.c_str()的话,不需要考虑字符串长度是否为0,在这种情况下,c_str()会返回一个空字符的指针。


c_str()返回的指针不可以被修改,返回的类型是const char*类型的指针。如果修改可以用const_cast<char*>(s.c_str)。


如果是其他容器,可以先把容器中的元素拷贝到vector中,然后再传给该C API。当然,C API里的数据也可以通过vector进行中转传给其他STL容器中。


17.使用"swap"技巧除去多余的容量。

vector<int> (v).swap(v);

string (s).swap(s);

C++11新标准有shrink_to_fit函数。


18.避免使用vector<bool>。

作为一个STL容器,vector<bool>只有两点不对,首先它不是一个STL容器,其次它并不存储bool。


标准库提供了两种选择。

第一种是使用deque<bool>,deque几乎提供了vector提供的一切(可以看到的省略只有capacity()和reserve()),但deque<bool>是一个STL容器,它也确确实实存储bool。当然deque的元素内存不是连续的,所以不能把deque<bool>传递给一个期望bool数组的C API。(也不能通过vector进行中间转换。)

第二种是采用bitset。


0 0