1.头文件不应该包含using声明
2.拷贝初始化和直接初始化:对于有连续多少个重复字符的用直接初始化
string s1="hello"; //拷贝初始化 string s2("hello"); //直接初始化 string s3(10,'c'); //直接初始化
3.string.size()返回的时string::size_type类型的值,可以用auto或者decltype获得其类型(事实上,返回的是一个unsigned int,注意避免和int混用造成由于越界导致的问题)
4.当string的加运算中,有string对象和字符字面值和字符串字面值混在一起时,注意确保每个+号两侧的对象中至少有一个是string
string s1="hello"; string s2=s1 + "world" + "!"; //错误 string s2=(s1 + "world") + "!"; //正确
5.使用基于范围的for循环,若想要改变原数据的内容,不要忘记加引用符号;基于范围的for循环不能改变所遍历序列的大小,因此不能用于向vector中添加元素
string s="hello world"; for(auto &c:s) c=toupper(c); cout<<s<<endl;
6.vector的几种初始化:等号赋值,圆括号(用于构造,指明有几个元素,初始值是啥),花括号(用于指定元素的初始值)
vector<T>v1; vector<T>v2(v1); vector<T>v3=(n,val); //有n个元素,初始值均为val vector<T>v4(n); //v4内有n个重复执行初始化了的值(我的编译器里:若为int类型,则有n个0) vector<T>v5{a,b,c...}; //使用列表初始化,必须要用花括号,不能用圆括号 vector<T>v6={a,b,c...};
但是对于如下,花括号也可以用于构造(当花括号内的值与元素类型相同时为指定元素的具体值,不相同时表示用于构造)
vector<string> v7{10} //v7有10个默认初始化的string元素 vector<string> v8{10,"ji"} //v8有10个默认初始化为"ji"的元素
7.若vector和strinng是常量时,要用迭代器只能够使用const_iterator来访问,不可修改;对于普通变量使用iterator和const_iterator均可
vector<int>::const_iterator it3; string::const_iterator it4;
8.如果对象只需要读操作二不需要写操作,迭代器访问最好使用cbegin()和cend()
vector<int> v; vector<int> cv; auto it1=v.begin(); //it1的类型为vector<int>::iterator auto it2=cv.begin(); //it2的类型为vector<int>::const_iterator auto it3=v.cbegin(); //it3的类型为vector<int>::const_iterator,若只想读,最好用此
9.凡是使用了迭代器的循环体中,都不要向迭代器所属容器里添加元素。
10.字符数组或自动加上一个空字符,数组不允许直接拷贝,但是vector可以直接拷贝
char a1[]={'c','+','+'}; //维度是3,但是strlen他的结果是未定义 char a2[]="c++"; //维度是4 char a3[]=a1; //错误,不允许使用数组初始化另一个数组 a3=a1; //错误,不能把一个数组直接赋值给另一个数组,注意这里别把a3当做一整形个指针,在上一行定义处没指定维数就会报错
11.数组指针和指针数组(从内到外读)
int *ptrs[10]; //ptrs是含有十个整形指针的数组 int &refs[10]; //错误:不存在引用的数组,引用不是对象 int (*Parray)[10]; //Parray是数组指针,该数组含有十个整数 int (&arrRef)[10]; //arrRef是数组引用,该数组含有十个整数 int *(&arry)[10]; //arry是数组的引用,该数组含有10个整形指针
12.对于数组的迭代器就是指针,可用通过begin()和end()函数来获取数组的头尾(注意不是成员函数),事实上,这样我们也就理解了为什么指针和字面值相加,两个指针相减得到的是元素个数的间距,而非真正的地址偏移(指针看做迭代器)
话外:如果p为空指针,允许给他加上或减去一个值为0的整形常量表达式,两个空指针也允许彼此相减,结果为0
int *pbeg=begin(arr); int *pend=end(arr); //找到第一个负元素 while(pbeg!=pend && *pbeg>=0) pbeg++;
13.标准类型库string,vector也能够执行下标运算,但是其下标必须是无符号类型,而数组的内置下标无此要求,可以为负数
int *p=&a[2]; int k=p[-1]; //k的值为a[1]
14.string与字符数组,vector与C数组的转化
//字符数组和string string s("hello world"); const char *str=s.c_str(); //数组和vector int arr[]={1,2,3,4}; vector<int> vec(begin(arr),end(arr)); //vec中的内容是数组arr的拷贝 vector<int> vec1(arr+1,arr+4); //将指针看成迭代器,vec1内容为{2,3,4}
15.要使用范围for循环处理多维数组,出了最内层的数组,其他所有循环的控制变量都必须是引用类型(干脆都加上得了),否则编译器会将数组转化为整形指针,进而导致编译错误
int main(){ int a[][3]={{0,1,2}, {1,2,3}, {2,3,4}}; //使用基于范围for循环 for(auto &row:a){ for(auto col:row){ cout<<col; } cout<<endl; } //使用指针访问,使用a,a+3这样形式也可以,但是用begin(),end()更简洁 for(auto p=begin(a);p!=end(a);p++){ for(auto q=(*p);q!=end(*p);q++) cout<<*q; cout<<endl; } return 0; }
16.两个迭代器相减,得到的类型是difference_type