一. c++语法
1.初始化
int main()
{
int a = 10;
int b(10) ;
int b();//error 与C兼容 当成函数了
int c{10} ;
int c{};//初始化为0
int ar[10] ={1,2,3,4,5,6,7,8,9,10};
int br[10]{1,2,3,4,5,6,7,8,9,10};
int br[10]{};//0
return 0;
}
float b = 12.23;
int a = b;//隐式转换
int a = {b};//error
int a{b};//error 花括号有很强的类型转换
int a{(int)b};//true
2.输入输出
int a ;
char b,c;
cin>>a>>b;
cout<<a<<b<<endl;
cin>>a,b;//error,只能是一个,另一个输不进去
cout<<b,c;//error
cin时只能输入一个变量,cout也是一样的,只能输出一个变量,若多个输入输出用连续的"<<“或”>>"就行
const int n = 5;
char str[n];//c++中,数组大小可用常变量
cin>>str;//不安全,可能会越界,
cin.getline(str,n,'#');//给str,不超过n个,以'#'作为结束标志(没有默认结束'\n'),不包括
cin是以空格或换行符作为分割符,以换行作为结束符
3.const
在c++中const是以常量为主,在编译过程中,会把const的变量用相应的值来替换,相当于宏替换一样
const int n = 10;
int *p = (int*)&n;//强转 相当于把const去掉了,但不安全
*p = 100;//通过*p来改变n
int b = n;//但此时的n并不是变量,而是常量10,在c++中,在编译时会把n都用10替换掉
并且在同类型指针赋值时,只能是强的给弱的
int main()
{
int a = 10, b = 20;
const int* p = &a;//p时*被const 不能改变*p的地址
int* s1 = p;//error 弱给强 错的都是可以改变*s也就是*p
const int* s2 = p;//true
int* const s3 = p;//error p是*被const了,相同情况至少也是*被const才算一样强,但是这相当于不同的弱给了弱
const int* const s4 = p;//true 弱的给更弱的
int* const p = &a;//全对 const修饰的是p 不能改变p的值
int* s1 = p; //就是s1~s4的值变了,也不妨碍p的值不变
const int* s2 = p;
int* const s3 = p;
const int* const s4 = p;
}
4.引用
-
引用必须初始化,
-
函数形参数为指针时,首先就要对指针进行判空,而不存在空引用
-
不存在二级引用,不能被多次引用
-
常变量的,引用也必须加const
int a = 10;
const int &b = a;//true 不能通过b来改变a
const int &b = 10;//true
//为了安全
//int tmp = 10;
//const int& b = tmp;
int& const b = a; //编译器把const忽略了
const int b = 20;
int &c = b;//error 可以通过c来改变b
const int &c = b;//true
-
可引用数组某一个下标的值
-
ar和&ar是不一样的,ar是首元素的地址,&ar是整个数组的首地址
int a = 10;
int *p = &a;
int* &a = p;//a是一个引用,指针的引用
int &arr[10];//error 引用相当于别名,不开辟空间 而数组需要开辟空间
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int(*p1)[10] = arr;//error 编译不通过 p1指向的是一个int类型、10个元素的数组,不能指向一个数组元素
int(*p1)[10] = &arr;//true p1+1和代表走了10个格子
p1[2] = 10;//error *(p1+2)这里的+2走了20个格子 明显越界了
int *q1 = arr;//true q1+1代表走了一个格子 arr指的是数组首元素的地址
int *q1 = &arr[0];//同上一个意思
q1[2] = 10;//true
int *q1 = &arr;//error 编译不通过 不能拿整个数组的首地址,给一个int*的指针
int(&q2)[10] = &arr;//error
int(&p2)[10] = arr;//true p2是arr的别名,在引用时要明确声明p2是一个数组的别名
//int(* const p2)[10] = &arr;
p2[2] = 10;//true 虽然实质是指针,但这里是在语法上说明的,p2是arr的别名
int brr[10][10]{};
int (&b)[10][10] = brr;//true; b是brr的别名
b[0][0] = 5;//true
int &p2 = arr;//error 这里的arr是地址
int &p2 = arr[0];//true 这里是对arr[0]的引用
p2[0] = 8;//error p2是arr[0]的别名
p2 = 8;//true
-
引用语法概念:引用就是别名
-
虽然引用编译上是指针,但对引用sizeof,是语法上的,对数组引用sizeof,就是数组的大小,对double引用sizeof就是double的大小
int arr[10]{};
int &p = arr;
cin<<sizeof(arr)<<endl;//40
cin<<sizeof(p)<<endl;//40
- 不可以对函数中的局部变量或对象以指针或引用的方式返回:因为指针和引用本质是将当前的地址先储存在一个临时变量里,然后给相应的变量,函数结束后会释放掉内存,系统可能会在该地址上重新为某个变量或函数开辟内存,就会将当前的地址的值发生改变
5.inline
-
当程序执行函数调用时,系统要建立栈空间,保护现场,传递参数以及控制程序执行的转移 。
-
函数简短时可在函数头部加上inline,该函数会在编译时嵌入代码,节省函数调用的开销,效率会更高
inline是一种以空间换时间的做法,省去调用函数额开销。
但当函数体的代码过长或者是递归函数即便加上inline关键字,也不会在调用点以内联展开该函数。如果函数的执行开销大于开栈清栈开销,使用普通函数方式处理。
inline int Max(int a,int b)
{
return a>b?a:b;
}
- 不建议将inline函数的定义和声明分开,会导致链接错误 ,因为inline被展开、就没有函数地址了
- 内联函数与宏定义区别:
(1)内联函数在编译时展开,带参的宏在预编译时展开。
(2)内联函数直接嵌入到目标代码中,带参的宏是简单的做文本替换。
(3)内联函数有类型检测、语法判断等功能,宏只是替换。