你发现了奇怪的笔记二(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 逻辑错误;使用一个超出有效范围的值
C++