C++ 对于顺序容器的操作(vector、string、deque、list、forward_list、array)
这几个容器每个都有其特有的操作:
vector : 支持push\_back()、pop\_back()、insert()、emplace()、back()、front()、at(n)、emplace_front、emplace\_back()、erase()、V[n]。
list : 支持push\_back()、pop\_back()、insert()、emplace()、back() 不支持随机访问
array : 所有改变容器大小的操作,这个都不支持,都不支持,都不支持。支持随机访问 at()、back()、front()、a[n]。
string : 特殊的vector。
push_back(args): 向容器尾部填入值。
pop_back(): 删除容器尾部值。
insert(iter,args): 向容器迭代器所指向的前一个位置插入值。
push_front : 向容器首部插入元素。
随机访问操作: at(n)、V[n]。 两者不同之处在于,如果n超出容器范围,则会引发一个异常,而V[n]不会。
erase(V.begin(),V.end()): 删除容器该范围元素。
emplace、emplace\_front、emplace\_back 与 insert、push\_front、push\_back 作用相同,只是它将参数传递给元素的构造函数。
Example vector operation:
#include<iostream>
#include"myvect.h"
using namespace std;
struct book{
book(string booknamel,int bookpricel,vector<string> &editionl):bookname(booknamel),bookprice(bookpricel),edition(editionl) {
}; //构造函数的初始化
string bookname="python";
int bookprice=0;
vector<string> edition;
}; //定义一个book类的对象
int main()
{
//这个区域就是定义一些容器和用到的变量。
vector<string> str{"facebook","github","google","intel","IBM"};
const char *cp_1="Hello World!";
vector<string> stt{"nn","aa","cc"};
cout<<"change before:"<<endl;
string str_5="hahahah";
vector<book> program;
for(auto i :str)
{
cout<<i<<"\t";
}
cout<<endl;
operate_v(str,cp_1); //函数定义在myvect.h里
cout<<"change after:"<<endl;
for(auto i:str)
{
cout<<i<<"\t";
}
cout<<endl;
auto ito_1=stt.begin();
auto ito_2=str.begin();
auto ito_3=stt.end();
cout<<"change before:"<<endl;
for(auto i :str)
{
cout<<i<<"\t";
}
cout<<endl;
operate_v(str,ito_2,ito_1+2,ito_3,str_5); //函数定义在myvect.h里
operate_v(str,cp_1);
cout<<"change after:"<<endl;
for(auto i:str)
{
cout<<i<<"\t";
}
cout<<endl;
program.emplace_back("c++",100,stt);
for(auto pro: program)
{
cout<<pro.bookname<<"\t";
cout<<pro.bookprice<<"\t";
for(auto i:pro.edition)
{
cout<<i<<"\t";
}
}
cout<<endl;
cout<<str.at(2)<<endl;
return 0;
}
myvect.h
#include<vector>
#include<string>
void operate_v(std::vector<std::string> &str_1,const char *cp);
void operate_v(std::vector<std::string> &str_1,std::vector<std::string>::iterator itr_1,std::vector<std::string>::iterator itr_2,std::string str_2);
void operate_v(std::vector<std::string> &str_1,const char *cp)
{
str_1.push_back(cp);
}
void operate_v(std::vector<std::string> &str_1,std::vector<std::string>::iterator itr_1,std::vector<std::string>::iterator itr_2,std::vector<std::string>::iterator itr_3,std::string str_2)
{
str_1.insert(itr_1,str_2);
str_1.insert(itr_1,{"1233455","223344551"});
str_1.insert(itr_1,itr_2,itr_3);
}
Run:
xiandonghua@HappyDay:~/c++/c++bin/ch5$ ./tes
change before:
facebook github google intel IBM
change after:
facebook github google intel IBM Hello World!
change before:
facebook github google intel IBM Hello World!
change after:
cc 1233455 223344551 hahahah facebook github google intel IBM Hello World! Hello World!
c++ 100 nn aa cc
223344551
resize 可以改变容器当前包含当前元素的大小,确切可以访问的单元。就是说它可以缩小我们给容器存储确定值的空间的大小,也可以增大容器当前的大小,并且初始化容器增加之后存储单元的值。这个空间是存储了容器确定的值,不是容器理论上预留的大小。
resize 用法
void resize( size_type count, T value = T() ); (until C++11)
void resize( size_type count ); (1) (since C++11)
void resize( size_type count, const value_type& value ); (2) (since C++11)
example :
void resizes(std::vector<std::string> &V,std::vector<int> &int_V,const size_t n,std::string demo)
{
V.resize(n,demo); //传递了两个参数,一个容器大小,一个容器添加的存储单元默认值。
int_V.resize(n); //传递了一个参数,只有容器大小,添加存储单元的默认值由系统自动分配,默认为0。
}
size_t size_v;
string init_str;
vector<string> classes{"home","name","id","age","gender"};
vector<int> age{1,2,3,4,5,6,100};
cout<<"Please enter you want to change size of the vector:"<<endl;
cin>>size_v;
cout<<"Please enter your initialization parameter:"<<endl;
cin>>init_str;
resizes(classes,age,size_v,init_str);
cout<<"string type container:"<<endl;
for(auto i: classes)
{
cout<<i<<"\t";
}
cout<<endl;
cout<<"int type container:"<<endl;
for(auto i: age)
{
cout<<i<<"\t";
}
cout<<endl;
RUN:
Please enter you want to change size of the vector:
10
Please enter your initialization parameter:
ni
string type container:
home name id age gender ni ni ni ni ni
int type container:
1 2 3 4 5 6 100 0 0 0
需要说明的是因为 C++98 标准不支持 auto .所以用到的编译器 应遵循 c++11标准以上。
例如我用的gcc 编译器
xiandonghua@HappyDay:~/c++/srccode/ch5$ g++ tes.cpp -o ../../c++bin/ch5/tes -std=c++11
vector 和 string 在存储的时候是顺序存储,一个值紧挨着下一个值,所以在添加新的元素的时候,可能会因为没有足够后大小的单元去存储,因为容器下一个单元存储别的内容,所以容器会被移动到新创建的容器存储单元当中进而导致指针,引用,迭代器,失效。也会导致速度变慢,因为有一个转移的过程。
那么如何改变容器预留大小呢? ——-> reserve
那么如何查看容器当前预留大小呢? —–> capacity
example :
cout<<endl<<"age 当前预留大小: "<<age.capacity()<<" age 当前容器大小: "
<<age.size()<<endl;
age.reserve(100);
cout<<"age 改变后预留大小: "<<age.capacity()<<endl;
RUN:
age 当前预留大小: 14 age 当前容器大小: 10
age 改变后预留大小: 100
当使用reserve 改变容器预留大小之后,如果添加元素超过当前设置的大小是可行的,并且capacity 的值发生改变。
capacity 与 size 的区别
显而易见,capacity 是容器预留大小的值,而size是容器目前实际大小的值,在一定范围内size的值与capacity 的值是一样的。
建议:在传递容器大小的值是尽量用size_type 类型。因为int类型是有符号的值,而size_type是无符号类型的值,有时候在比较上或其它用法上会有很多异常行为。
一步一步慢慢学,不怕学的比别人慢,就怕什么也没学。