C++ Primer_顺序容器杂记(四)

2014-11-24 12:32:32 · 作者: · 浏览: 12
必复制任何已存在的元素。


由此可以推论:一般而言,使用 list 容器优于 vector 容器。但是,通常
出现的反而是以下情况:对于大部分应用,使用 vector 容器是最好的。原因在
于,标准库的实现者使用这样内存分配策略:以最小的代价连续存储元素。由此
而带来的访问元素的便利弥补了其存储代价。


为了使 vector 容器实现快速的内存分配,其实际分配的容量要比当前所需
的空间多一些。vector 容器预留了这些额外的存储区,用于存放新添加的元素。
于是,不必为每个新元素重新分配容器。所分配的额外内存容量的确切数目因库
的实现不同而不同。比起每添加一个新元素就必须重新分配一次容器,这个分配
策略带来显著的效率。事实上,其性能非常好,因此在实际应用中,比起 list 和
deque 容器,vector 的增长效率通常会更高。


capacity 和 reserve 成员


vector 类提供了两个成员函数:capacity 和
reserve 使程序员可与 vector 容器内存分配的实现部分交互工作。capacity
操作获取在容器需要分配更多的存储空间之前能够存储的元素总数,而 reserve
操作则告诉 vector 容器应该预留多少个元素的存储空间。


弄清楚容器的 capacity(容量)与 size(长度)的区别非常
重要。size 指容器当前拥有的元素个数;而 capacity 则指容
器在必须分配新存储空间之前可以存储的元素总数。


编写程序研究vector容器的内存分配策略:


view plain
#include
#include
using namespace std;

void print(vector::iterator beg,vector::iterator end)
{
if(beg==end)
cout<<"Nothing to display !"< else
{
while(beg!=end)
cout<<*beg++<<" ";
cout< }
}

int main()
{
vectorv;
print(v.begin(),v.end());
cout<<"size :"< for(int i=1;i<=11;i++)
{
v.push_back(i);
print(v.begin(),v.end());
cout<<"size :"< }
v.reserve(20);
cout<<"size :"<<20<<" "<<"capicity :"< v.reserve(50);
cout<<"size :"<<50<<" "<<"capicity :"< v.reserve(100);
cout<<"size :"<<100<<" "<<"capicity :"< system("pause");
}


容器的选用


元素是否连续存储还会显著地影响:
1. 在容器的中间位置添加或删除元素的代价。
2. 执行容器元素的随机访问的代价。


程序使用这些操作的程序将决定应该选择哪种类型的容器。vector 和 deque
容器提供了对元素的快速随机访问,但付出的代价是,在容器的任意位置插入或
删除元素,比在容器尾部插入和删除的开销更大。list 类型在任何位置都能快
速插入和删除,但付出的代价是元素的随机访问开销较大。


插入操作如何影响容器的选择


list 容器不支持随机访问,访问某个元素要求遍历涉及的其他元素。


deque 容器拥有更加复杂的数据结构。从 deque 队列的两端插入和删除元素
都非常快。在容器中间插入或删除付出的代价将更高。


通常来说,除非找到选择使用其他容器的更好理由,否则
vector 容器都是最佳选择。


如果无法确定某种应用应该采用哪种容器,则编写代码时尝试
只使用 vector 和 lists 容器都提供的操作:使用迭代器,而
不是下标,并且避免随机访问元素。这样编写,在必要时,可
很方便地将程序从使用 vector 容器修改为使用 list 的容
器。


string类型不支持以栈方式操纵容器:在 string 类型中不能使用 front、back 和 pop_back 操作


Exercise
9.34:
使用迭代器将 string 对象中的字符都改为大写字母。
Exercise
9.35:
使用迭代器寻找和删除 string 对象中所有的大写字
符。
Exercise
9.36:
编写程序用 vector 容器初始化 string 对象。

view plain
#include
#include
#include
#include
using namespace std;

int main()
{
//使用迭代器将 string 对象中的字符都改为大写字母
string str("Hello Ubuntu !");
cout< string::iterator it=str.begin();
while(it!=str.end())
{
if(islower(*it))
*it=toupper(*it);
it++;
}
cout< //使用迭代器寻找和删除 string 对象中所有的大写字
str="Hello Ubuntu !";
cout< it=str.begin();
while(it!=str.end())
{
if(isupper(*it))
it=str.erase(it);
else
it++;
}
cout< //编写程序用 vector 容器初始化 string 对象。
string str1("Hello Ubuntu !");
vectorvec(str1.begin(),str1.end());
string str2(vec.begin(),vec.end());
cout< system("pause");
}

Exercise
9.38:
已知有如下 string 对象:
"ab2c3d7R4E6"

编写程序寻找该字符串中所有的数字字符,然后再寻找
所有的字母字符。以两种版本编写该程序:第一个版本
使用 find_first_of 函数,而第二个版本则使用
find_first_not_of 函数。

view plain
#include
#include
using namespace std;
int main()
{
string str("ab2c3d7R4E6");
string numerics("1234567890");
string alpha("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
//find_first_of
//number
string::size_type pos=0;
while((pos=s