《重学C++》5. 彻底学会 C++ 指针,引用(一)指针和左值右值
1. 左值和右值
概念:
一般说法,编译器为左值单独分配了一块存储空间,可以取其地址。左值可以放在赋值运算符左边也可以在右边;
右值指的是数据本身;不能取到其自身地址,右值只能赋值运算右边;
左值代表地址单元,右值代表数据本身。
左值最常见的情况如函数和数据成员的名字;
右值是没有标识符、不可以取地址的表达式,一般也称之为“临时对象”。
比如:
a = b + c;
&a是允许的操作,而&(b+c)不能通过编译,因此a是一个左值,而(b+c)是一个右值。
1 | char strHelloWorld[] = {"helloworld"}; |
理解C和C++中的左值和右值
https://blog.csdn.net/xuwqiang1994/article/details/79924310
2. 指针和数组
指针的数组(array of pointers)与数组的指针(a pointer to an array):
指针的数组T* t[]
数组的指针 T(*t) []
1 | int* a[4]; //注意:[]优先级比较高,没有小括号时,a优先和[]结合,表明是数组; |
3. 指针和const
除了指针和数组容易混淆外,指针也容易和const混淆。
4. 原始指针
- 野指针:一般有三种情况:
1
2int *a;
*a=12; //出错,
- 指针变量没有初始化;
- 已经释放不用的指针没有置NULL,如delete和free之后的指针;
- 指针操作超越了变量的作用范围;
- 空指针: 空指针表明了该指针目前没有指向任何位置。
1
int *a = NULL;
指针要么被手动初始化指向一个地址,要么就应该被置为NULL。(尽量避免野指针,使用空指针)
同样,在使用一个指针前,要先判断其是否是NULL。
5. 指针和左值右值
一元取地址符 ‘**&**’ 拿一个左值作为参数并且生成一个右值:
1 | char ch = 'a';char* cP = &ch; |
上面的例子中,&ch和&cp都是只能作为右值而不是左值。
在取地址时,编译器记录变量的地址,并将其数值保存在临时变量中。而所有临时变量(它们均由编译器管理)只能取到数值,是右值的一种。
这里要想让&ch和&cp作为左值,只能手动将其保存为一个程序员管理的变量(而不是编译器内部管理的临时变量)。
一元运算符‘*****’(解引用)拿一个右值作为参数而产生一个左值作为结果:
*p会取到指针p的空间作为左值。由于左值可以作为右值使用,*p作为右值时取p指向的空间里的数值。
1 | *cp = 'a'; //*cp左值取变量ch位置 |
++和–运算符
1 | //++,--操作符 |
*和++组合运算符
注意:注意:++操作符的优先级高于取间接*操作符的优先级。
1 | //*++,++* |
6.读取运算符“贪心法”
编译器程序分解成符号的方法是:一个字符一个字符的读入,如果该字符可能组成一个符号,那么读入下一个字符,一直到读入的字符不再能组成一个有意义的符号。这个处理过程称为”贪心法”。
1 | int a = 1,b = 2,c; |
小练习:
表达式 ++*++cp 是什么含义?(提示:结合贪心法和堆栈)