《C++Primer 5e》学习笔记(2):字符串、向量和数组

1.作用域操作符(::)的含义:编译器应从操作符左侧名字所示的作用域中寻找右侧那个名字。当左侧名字为空时即为全局变量。

2.对于using声明:每个名字都需要有独立的using声明,且头文件中不应包含using声明。


3.标准库类型string(string是一个类)需要有头文件#include <string>和命名空间using std::string;

4.getline(is,s)函数的参数是一个输入流is和一个string对象s,函数从给定的输入流中饭读取内容,直到遇到换行符(注意换行符也被读进来了),然后把所读内容存入string对象中去(注意不存换行符)。

5.string类中的size()函数的返回值是一个string::size_type类型的值。其是一种与机器无关的类型,在具体使用的时候,可以通过作用域操作符(::)来表明名字size_type是在类string中定义的。它是一个无符号类型的值,而且能够存下任何string对象的大小。

6.两个字符串按字典序比较,当较短的字符串的内容和较长字符串中的前缀相同时,才说明较短的字符串小于较长的字符串;若元素的值有区别,则string对象的大小关系由第一对相异的元素值的大小关系决定。

7.当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)两侧运算对象至少有一个是string类型的对象(切记字符串字面值和string类型是不同的类型)。

string s1="hello world";
string s2=s1+'.'; //正确:把一个string对象和一个字符字面值相加
string s3=s1+"lhs"; //正确
string s4="hello"+"world"; //错误:两个运算对象都是string对象
string s5=s1+"lhs"+"myl"; //正确:每个加法运算符两侧都有一个string类型的对象
string s6="lhs"+"myl"++s1; //错误


8.范围for(range for)语句:for(dec:exp)

exp部分是一个对象,用于表示一个序列。dec部分负责定义用于访问序列中基础元素(比如访问vector<int> vs需要定义int类型的dec)的变量。每次迭代,dec部分的变量会被初始化为exp部分的下一个元素值。

string s="helloword";
for(auto ch:s) cout<<ch<<endl;


如果想要改变string中的内容,必须把循环变量定义成引用类型:

string s="helloword";
for(auto &ch:s)  ch=toupper(ch);
cout<<s<<endl;


此外,下标运算符([  ])接收的输入参数也是string::size_type类型的值。


9.标准库类型vector(vector是一个模板类)表示对象的集合,其中所有对象的类型都相同。需要头文件#include <vector>和命名空间using std::vector;

10.编译器根据模板创建类或函数的过程称为实例化。当使用模板时,需要指出编译器应把类或函数实例化成哪种领类型。其中,引用不是对象,故存在包含引用的vector。

11.vector对象初始化的真实含义依赖于传递初始值时用的是圆括号还是花括号:

用圆括号传递初始值时,第一个参数必须是数字(或是数组的指针,详见21条)或是和该对象类型相同的vector对象;

用花括号传递初始值时,一般表述为列表初始化。也就是说,初始化过程会尽可能的把花括号内的值当成是元素初始值的列表来处理,只有当无法执行列表初始化时才会考虑其他初始化方式。

vector <string> v1{"hi"}; //列表初始化,v1只有一个元素
vector <string> v2(v1); //将v1拷贝给v2
vector <string> v3(10); //v3有10个元素,初始值默认(string默认为空)
    
vector <string> v4("hi"); //错误
vector <string> v5{10}; //v5有10个默认初始化的元素
vector <string> v6{10,"hh"}; //v6有10个值为"hh"的元素


12.vector模板类定义了size()函数返回对象中元素的个数,其返回值类型是由vector定义的vector::size_type类型

13.vector实例化的对象可以比较(>,=,<)只有在实例化的类型支持比较时才可行。比较和string类型的比较相同(第6条)。

14.vector可用push_back()函数在尾部添加元素,但不能用下标的方式添加元素值(但可以用下标的方式来访问)。

15.迭代器用于间接访问标准库中的对象。与指针不同的是,获取迭代器不是使用取地址符,有迭代器的类型都拥有返回迭代器的成员函数:begin()和end()。其中begin()返回指向第一个元素的迭代器,end()返回指向容器"尾元素的下一位置"的迭代器,也就是说,该迭代器指示的是容器的一个不存在的"尾后"元素。如果容器为空,begin和end返回的是同一个迭代器----尾后迭代器。

vector <int> v{1,2,3,4,5,6,7,8,9};
for(auto i=v.begin();i!=v.end();i++)
    cout<<*i<<endl;

两个迭代器相等,当且仅当两个迭代器指向的元素相同或者都是同一个容器的尾后迭代器。迭代器的类型如下:

vector <int>::iterator i; //i能读写vector<int>的元素
string::iterator is; //is能读写string对象总的字符
    
vector <int>::const_iterator ii; //ii只能读元素,不能写元素
string::const_iterator iss; //iss只能读元素,不能写元素

和begin()返回iterator一样,C++定义了成员函数 cbegin()来返回const_iterator。

16.两个迭代器相减的结果是他们之间的距离(其类型为difference_type,是一个带符号的整数型)。也就是说,讲运算符右侧的迭代器向前移动差值个元素将得到左侧的迭代器。参与运算的两个迭代器必须是指向同一个容器的元素或者尾元素的下一位置。同理定义迭代器的大小比较(>,≥,=,≤,<)操作,如果某迭代器指向的容器位置再另一迭代器所指位置之前,则说前者小于后者。

17.数组不允许拷贝和赋值(也不允许用vector容器赋值):

int a[]={3,1,2};
int a1[]=a; //错误:不允许用一个数组去初始化另一个数组
a1=a; //错误:不能把一个数组直接赋值给另一个数组


18.数组的下标类型为size_t。是一种机器相关的无符号类型,它被设计的足够大以便能表示内存中的任意对象的大小。在<cstddef>头文件中定义了size_t类型。

19.使用数组的时候编译器会把它转换成指针。C++也为数组提供了和容器的成员函数类似的begin和end函数(这两个函数定义在头文件<iterator>中):

int a[]={1,2,3,4,5,6,7,8,9};
int *head=begin(a); //指向a首元素的指针
int *tail=end(a); //指向a尾元素的下一位置的指针
for(;head!=tail;head++)
     cout<<*head<<endl;


20.指针作为迭代器的一种,和迭代器一样也可以相减。两个指针相减的结果是他们之间的距离(参与运算的指针必须是指向同一个数组当中的元素)。两个指针相减的结果的类型为一种叫做ptrdiff_t的标准库类型。ptrfiff_t也是一种定义在头文件<cstddef>中的机器相关的类型。由于距离可正可负,因此ptrdiff_t也是一种带符号类型。

int a[]={1,2,3,4,5,6,7,8,9};
auto dis=end(a)-begin(a);
cout<<dis<<endl; //dis=9:即为数组a中元素的个数


21.使用数组初始化vectoe对象:

int a[]={1,2,3,4,5,6,7,8,9};
vector <int> vs(begin(a),end(a)); //正确:用a[0..8]初始化vs
vector <int> vs1(a+2,a+8); //正确:用a[2..8]初始化vs1




猜你喜欢

转载自blog.csdn.net/AC_Gibson/article/details/50402678