你发现了奇怪的笔记二(C++)
内置数组
定义
- 长度必须是常量表达式--》但是因为有编译器扩展,目前我没发现变量类型报错的编译器(C++11)
- 下表类型size_t(c++版本的在头文件stddef.h)中
unsigned cnt = 42;//不是常量表达式
constexpr unsigned sz=42;//常量表达式
int arr[10];//含有10个整数的数组
int *parr[sz];//含有42个整型指针的数组
string bad[cnt];//错误,cnt不是常量表达式,不报错的是因为编译处理,这叫编译器扩展,编译器自定义的辅助功能
string strs[get_size()]; //当get_size()是constexpr时正确
初始化
const unsigned sz=3;
int ial[sz] = {0,1,2};
int a2[]={1,2,3};
int a3[5]={1,2,3};//等价于{1,2,3,0,0}
string a4[3]={"hi","bye"};//等价于{"Hi",bye",""}
int a5[2]={0,1,2};//报错,初始值过多
字符数组的特殊性
char a1[]={‘c',’+‘,’+‘};//列表初始化,没有空字符
char a2[]={'c','-','-','\0'};//列表初始化,含有显示的空字符
char a3[]="C++";//自动添加表示字符串的结束空字符
const char a4[6] ="Daniel";//错误,6个字符,没有位置存放空字符
不允许拷贝和赋值
int a[]={0,1,3};
int a2[]=a;//错误,不能拷贝
a2 = a;//错误,不能赋值
指针和数组
数组的auto和decltype
- auto:对数组推断得到的是指针
- decltype:对数组推断得到的还是数组
int ia[]={1,2,3,4};
auto ia2(ia);//ia2是一个指针,指向ia的首元素
id2 = 42;//错误
auto id3(&ia[0]);//显然也是一个指针类型
decltype(ia) id4={0,1,3,4};
int *p=&0x111;-->假设。。
ia4 = p;//错误,不能用整型指针给数组赋值
ia4[4] = i;//正确,把i的值赋给ia4的一个元素
迭代器
int arr[]={1,2,3,4};
int *beg = begin(arr);//指向首地址的指针
int *last=end(arr);//指向arr尾元素的下一个位置的指针
指针运算
- 只支持加减运算
- 相减结果(他们之间的距离)类型为ptrdiff_t的标准库类型,和size_t在同一个头文件。
下标和指针
int ia[]{1,2,3,4,5,6}
int *p=ia;
i=*(p+2);
------------------------
int *p=&ia[2];--->注意:是ia[2],指向的是ia[2]作为指针所指向的地址
int j=p[1];//等价于ia[3]
int k=p[-2];//等价于ia[0]
数组的比较
- 两个数组的比较总是false
- arr==brr---->两数组首地址不可能相等
C风格字符串
头文件cstring
方法
方法 | 解释 |
---|---|
strlen(p) | 返回p的长度,不记空字符 |
strcmp(p1,p2) | 比较p1和p2的相等性。如果p1==p2,返回0;如果p1>p2返回一个正值;如果p1 |
strcat(p1,p2) | 将p2附加到p1之后,返回p1 |
strcpy(p1,p2) | 将p2拷贝给p1,返回p1 |
一个严重错误
传入此类函数的指针必须指向以空字符作为结束的数组
char ca[] = {'c','+','+'};
cout<
字符串与旧版本的接口
string s("hello");
char *str = s;//错误,不能用string对象初始化char*
const char *str=s.c_str();//正确
多维数组
要使用范围for语句处理多维数组,除了最内层循环外,其他所有循环的控制变量都应该是引用类型
size_t cnt=0; for(auto &row:ia) for(auto &col:row) {//改写。两个& ... } for(auto &row:ia) for(auto col:row) {//不改写,一个& cout<
取模
参与取余运算的运算对象必须是整数类型
正负
取模运算的结果正负有分子决定,分子负则负,分子正则正
21%6=3 21%7=0 -21%-8=-5 21%-5=1
比较运算符
- 除非是bool类型,否则不要使用布尔字面值true和false作为运算对象
类型转换
- 不允许const转换成非常量
int i;
const int &j=i;
const int *p=&i;
int &r=j,*q=p;//错误
- static_cast
任何具有明确定义的类型转换,只要不包括底层const,都可以使用
double slope = static_cast
(j)/i;//强制转换成double类型
- const_cast
只能改变运算对象底层const,重载中尤其有用(P209)。
const char *pc; char *p=const_cast
(pc);//可以改写pc指向的类容了。 char *q=static_cast (pc);//错误,static_cast不能去掉const性质
- reinterpret_cast
非常危险的转换。不建议使用。通常为运算对象的位模式提供底层的重新解释。
- 旧版本转换()
do while
do while语句应该在括号包围起来的条件后面用一个分号表示语句结束
---》因为对于do while来说,先执行语句或者块,后判断,所以不允许在条件部分定义变量
do{
}while(int i=0);//错误
跳转语句
-
break:终止(跳出)离它最近的while,do while.fow.switch
-
continue:终止本次循环,开始下一次新的循环。不是跳出。
-
goto:无条件跳转。 goto end; end:
-
return:跳出当前函数。在含有return语句的循环后面应该也有一条return语句,如果没有程序是错误的。
异常
try语句块
try{
}cast(exception-declaration){
}cast(exception-declaration){
}//.....
标准异常
-
头文件:
#include
-
异常类 解释 exception 最常见的问题 runtime_error 只在运行时才能检测出的问题 range_error 运行时错误;生成的结果超出了有意义的值域范围 overflow_error 运行时错误;计算上溢 underflow_error 运行时错误;计算下溢 logic_error 程序逻辑错误 domian_error 逻辑错误;参数对应的结果值不存在 invalid_argument 逻辑错误;无效参数 length_error 逻辑错误;试图创建一个超出该类型最大长度的对象 out_of_range 逻辑错误;使用一个超出有效范围的值
-