C++ primer(第3章)-阅读笔记

范围for语句(range for)

范围for语句是对给定序列中的每个元素并对序列中的每个值进行某种操作,其语法形式为:

string str("some string");
// 输出str中的每个字符
for (auto c : str){
	cout << c << endl ;
}

标准库类型vector

标准库类型vector表示对象的集合,其中所有对象的类型都相同。vector容纳中其他对象,因此这也被称为容器(container)。要使用vector,需要添加适当的头文件

#include <vector>
using std::vector ;

vector<int> ivec ; // 定义int类型的ivec
vecor<Sales_item> Sales_vec ; // 保存Sales_item类型的对象

这里,vector<变量类型> 含义为:vector本质上是一个类模板,编译器在创建类的过程会对其进行实例化(instantiation),当使用这个模板时,需要指出要把类转化为何种类型。换句话说:vector并不是一个数据类型,而是一个模板,因此需要指出vector中元素的类型,例如vector < int >。
下面给出定义与初始化vector对象的样例

vector<T> v1 ; //T代表实际使用的类或者变量类型
vector<T> v2(n,val); //包含n个重复的元素,每个元素的值都是val
vector<T> v3{a,b,b...} ; //包含了初始值个数的元素,每个元素被赋相应的值
vector<T> v4 = {a,b,c,...}; //等价于v3

注:不能使用下标的形式来添加元素,但是可以通过下标进行元素访问,看下面的例子

vector<int> ivec;
// ivec[0] = 1; 错误,ivec不包含任何元素,还是一个空的vector
ivec.push_back(1);
cout << ivec[0] << endl;
//当这个元素存在的时候,也是可以通过下标来进行值更改的
ivec[0] = 2;
cout << ivec[0] << endl;

迭代器

要访问string对象或者vector对象的字符,除了使用下标进行访问之外,还可以使用迭代器
在所有的标准库的容器中,都可以使用迭代器,但是其中只有少数几种才同时支持下标运算符。严格而言,string对象并不是容器类型,但是string支持很多容器类似的操作。
和指针不一样的是,获取迭代器不是取缔支付,有迭代器的类型会返回迭代器的成员。这些类型都拥有begin和end的成员,其中begin成员负责返回指向的第一个元素。有如下语句:

auto b = v.begin(); //b表示第一个元素
e = v.end(); //e为尾元素的下一个位置

若容器为空,那么begin和end会返回同一个迭代器,都是尾后迭代器。
迭代器运算符
迭代器中市场使用 == 和 !=来进行判断

for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it){
	*it = toupper(*it);  //将当前字符转换成大写形式
}

泛型编程的概念:我们在for循环中时常使用的是<=判断结束条件,而迭代器更喜欢使用==和!=。
迭代器类型

vector<int>::iterator it ; //it能读写vector<int>中的元素
vector<int>::const_iterator it2 ; //it2只能读元素,不能写元素

结合解引用和成员访问操作

解引用可以获得迭代器所指向的对象,如果该对象的类型恰好是类,那么久可能希望进一步访问他的成员。
例子:一个由字符串组成的vector对象,要检查其元素是否为空,则:

(*it).empty()
*it.empty(); //错位,试图访问it的empty成员,但是it是一个迭代器,没有这个成员

以上,圆括号必不可少,具体含义为先解引用,再对解引用的结果进行点运算。
c++中,为了简化上述操作,定义了箭头运算符** (->)**。即it->men与(*it).mem表达的意思相同。

某些vector对象的操作会使迭代器实效
虽然vector可以动态的增长,但是有时也会有一些副作用。已知的一个限制是不能在for循环内向vector添加元素。另外,一种是可能改变vector对象容量的操作例如push_back,都会使该vector对象的迭代器实效。

指针和数组

string nums[] = {"a","b", "c"} ;
string *p = $nums[0] ;  //p指向nums的第一个元素
string *p2 = nums; //数组的一个特性是,在一些用到数组名字的地方,编译器会自动将其替换成一个指向数据首元素的指针
int ia[] = {0,1,3,4,5} ;
auto ia2(ia) ; // ia是一个整型指针,指向ia的第一个元素
ia2 = 42; //错误,这是一个指针

指针也是迭代器
就像使用迭代器遍历vector对象中元素一样,使用指针也遍历数组中的元素。
通过数组名或者首元素的地址就可以得到指向首元素的指针,不过,要获取尾后指针就需要使用数组的一个特殊性质:获取尾元素后面那个不存在的元素的地址
例如,一个数组有10个元素
那么

int *e = &arr[10]; //指向arr元素的下一个位置的指针
for(int *b = arr; b != e; ++b){
	cout << *b << endl ;  
}

注:尾后指针不能执行解引用和递增操作。

下标和指针

int ia[] = {1,2,3,4} ;
int *p = ia ;
a = *(p+2) ; //等价于a = ia[2]
int *p2 = &is[2] ; //指向索引为2的元素
int k = p[-2] ;  //指向ia[0]的元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值