文章目录
- 类型转换:
- 强制类型转换
- 标准库类型vector
- 迭代器:
- 数组
- 数组形参
- 可变形参的函数
- 迭代器失效问题
- IO
- 泛型算法
类型转换:
无符号(0-255)
当赋给一个超出表示范围之后,初始值对无符号类型表示数值总数取模后的余数
unsigned char c = -1; //c的值为255
int i = -42;
unsigned u =10;
cout<<i-u; //42949672764
首先把整数-42转换成无符号数。类似于直接给无符号数赋一个负值,结果等于这负值加上无符号数的模。
String:
在cin>>字符串的时候遇到空格就会读取结束
例:Hello World,输出Hello,输出结果没有任何字符
比较:如果两个string对象在某些位置上不一致,结果就是string对象中第一对相异字符比较的结果
加法运算符的两侧的对象至少是一个string
string s1 = "hello";
string s2 = s1 + ',' + "world" + ","+'\n';//ok
//拆分 s2=(s1+',')+"world"
string s3 = "hello" + ","+s2;//err 不能把字面符直接相加
string s4 = "hello" + '\n';//ok
强制类型转换
- static_cast:任何具有明确定义的类型转换,只要不包含底层 const,都可以使用static_cast;
int i,j;double slope = static_cast<double>(j) / i;
,static_cast可以改变表达式的类型。 - const_cast:只能改变运算对象的底层const,只有const_cast能改变表达式的常量属性。(重载函数上下文使用 )
标准库类型vector
编译器根据模板创建类或函数的过程称为实例化
对于vector对象来说,直接初始化的方式适用于三种情况:一是初始值已知且数量较少;二是初始值是另一个vector对象的副本;三是所有初始值一样。
如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for语句
注意:vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素
迭代器:
但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素,会失效。
两个迭代器不能进行加法运算:mid = (beg+end) /2;//err
C++定义了迭代器的减法运算和迭代器与整数的加减运算,所以有序二分搜索使用mid = beg + (end-beg)/2
tip:如果不清楚元素的个数,请使用vector
数组
数组的维度必须是常量表达式
unsigned int cnt = 42;
const unsigned int sz = 42;
int *pattr[sz];
string bad[cnt];//cnt不是常量表达式
string strs[get_size()];//当get_size是constexpr是正确;否则错误
不允许拷贝和赋值
int a[] = { 0, 1, 2 };
int a2[] = a;//错误,不允许使用一个数组初始化另一个数组
a2 = a;//错误,不能把一个数组直接赋值给另一个数组
定义在全局作用域中的int类型数组默认初始化为0,而在局部就是一个未定义的奇异值;对于string类型的数组,不论在函数内还是函数外都默认初始化为空串。
相比于 vector 来说,数组有哪些缺点. 请列举一些。
【解答】 数组与 名字,需要通过其所在位置访问。 数组与 额外的元素,虽然在某些情境下运行时性能较好,但是与 vector 相比损失了灵活 vector 的相似之处是都能存放类型相同的对象,且这些对象本身没有 vector 的最大不同是,数组的大小固定不变,不能随意向数组中增加性。
具体来说,数组的维度在定义时己经确定,如果我们想更改数组的长度,只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组中去。我们也无法 像 vector 那样使用 size 函数直接获取数组的维度。如果是字符数组,可以调用 strlen 函数得到字符串的长度 : 如果是其他数组 , 只能使用 sizeof (array) /sizeof (array[0] )的方式计算数组的维度。
尾后指针不能执行解引用和递增操作
怎么区分顶层const和底层const?
指针本身是个常量表示顶层常量const;指针所指的对象是一个常量表示底层const,声明引用的const都是底层const。
int i = 0;
int *const p1 = &i; //顶层
const int ci = 42; //顶层
const int *p2 = &ci; //底层
const int const*p3 = p2; //左边的const是底层,右边的const是顶层
const int &r = ci; //声明引用的const,都是底层const
数组形参
如果传给函数的是一个数组,则实参自动转换成指向数组首元素的指针。
管理指针形参有三种方式:
- 要求数组本身包含一个结束标记,字符串最后一个字符为空字符。
void print(const char * cp)if(cp) while(*cp)cout<< *pt++;
- 传递指向数组首元素和尾后元素的指针。
while(beg!=end)
- 定义一个表示数组大小的形参 (size)
int j[]={0,1}print(j,end(j)-begin(j));
可变形参的函数
initializer_list:实参数量未知但所有实参类型相同
initializer_list<T>lst
{a,b, c…};
迭代器失效问题
向容器中添加元素和从容器中删除元素的操作可能会使指向容器元素的指针、引用或迭代器失效。一个失效的指针、引用或迭代器将不再表示任何元素。
程序必须保证每个循环步中都更新迭代器、引用或指针。让这些操作都返回迭代器iter = vi.insert(inter,1)//插入1;
,iter = vi.erase(iter)//删除iter的当前元素
。
不能保存end返回的迭代器
vector<int> v = {0,1,2,3,4,5};
auto begin = v.begin(),
end = v.end(); //保存尾迭代器的值是一个坏主意
while( begin != end )
{;
begin = v.insert(begin,42);//插入新值
begin += 2;//向后移动迭代器,跳过当前元素以及插入到它之前的元素
}
这里不要缓存end返回的迭代器 ,在每个循环步添加/删除元素后都重新计算end:while( begin != v.end())
更安全。
IO
IO属于不能被拷贝的类型,所以通过引用传递
ostream &print(istream &os ,const Sales_data &item)
构造函数没有返回类型,不能声明const
泛型算法
泛型算法不会执行容器的操作,算法永远不会改变容器大小。
特点:算法是通过迭代器操作容器,因此不能直接向/从容器添加、删除算法,无法改变容器大小
vector<string>words;
string word;// 不能直接操作容器words,分配一个内置类型变量操作
while(in>>word)
words.push_back(word);//让word尾插到容器words中