C++基础(操作符)
操作符优先级
在实际开发中,一次运算中往往有多个操作符,那么计算时该如何进行计算。这时就取决于操作符的优先级了,计算时按照操作符优先级高的先计算,优先级低的后计算。
优先级表:
1 | ::(作用域预算符) |
---|---|
2 | ++ – (后缀自增自减) () [] . -> |
3 | ++ --(前缀自增自减) + - (正负取反) ! ~ (type) * &(取地址操作符) |
4 | .* ->* |
5 | * / % |
6 | + - (加号 减号) |
7 | << >> |
8 | < <= > >= |
9 | == != |
10 | & (按位与) |
11 | ^ (按位异或) |
12 | | (按位或) |
13 | && |
14 | || |
15 | ? : |
16 | = += -= *= /= %= <<= >>= &= ^= |= |
总结:
1. 优先级
- 单目运算符 > 双目运算符 > 三目运算符。
2. 单目运算符优先级
- 结合性规定对于一元运算符是冗余的,只为完备而给出:一元前缀运算符始终从右到左结合,delete ++*p实际为delete(++(*p));而 一元后缀运算符 始终 从左到右 结合,a[1][2]++ 被解释为 ((a[1])[2])++。
3. 双目运算符优先级
- 四则运算运算符 > 移位运算符 > 关系运算符 > 逻辑位运算符 > 逻辑运算符 > 赋值运算符;
- 四则运算符中,+、- 优先级低于 *、/、%;
- 比较运算符中,==、!= 优先级低于 >、<、>=、<=;
4. 三目运算符优先级
- C 中,三元条件运算符拥有高于赋值运算符的优先级。因此,表达式 e = a < d ? a++ : a = d 在 C++ 中剖析成 e = ((a < d) ? (a++) : (a = d)),但在 C 中会由于 C 的语法或语义制约而编译失败
5. 其他
- 拥有相同优先级的运算符以其结合性的方向与各参数绑定。例如表达式 a = b = c 被分析为 a = (b = c) 而非 (a = b) = c,因为赋值具有从右到左结合性,但 a + b - c 被分析为 (a + b) - c 而非 a + (b - c),因为加法和减法具有从左到右结合性
逻辑操作与其他操作
- 逻辑操作和其他操作都能单独使用,但逻辑运算符也可以将两个或多个关系表达式连接成一个或使表达式的逻辑反转。
自增与自减
例如:
a=1;b=1;
c=a++;
d=++b;
c=1,d=2;
1、自增前操作是先赋值后运算(即先c=a,后a++),自增后操作是先运算后赋值(即先b++,d=b),自减一样。
2、指针的自增与自减
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。由于指针的特殊性,指针的自增则是指针往下移一位;自减则是往上移一位。
左值与右值
- 左值lvalue:可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。在C语言中,左值最初指的是出现在赋值语句左边的实体,但这是引入const之前的情况。now,常规变量和const变量都可视为左值,因为可通过地址访问它们。常规变量属于可修改的左值,const变量属于不可修改的左值。左值基本上和以前的认知没有太大的改变。
- 右值rvalue:字面常量(用括号括起来的字符串除外,因为它们表示地址)、包含多项的表达式以及返回值的函数(条件是该函数返回的不是引用)。
- 区别:右值就是一个临时变量,只有临时地址空间,左值有其地址空间,换句话说,使用取地址符&对某个值取地址,如果不能得到地址,则是右值!
变量
1、变量的定义:
- 变量其实只不过是程序可操作的存储区的名称。C++
中每个变量都有指定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。 - 变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C++ 是大小写敏感的。
2、初始化:
C++中变量的初始化有很多种方式,如:默认初始化,值初始化,直接初始化,列表初始化。
1、默认初始化:默认初始化是指定义变量是没有指定初值时进行初始化操作。
例如:int a;
默认初始化的规则:
-
1、内置类型变量的初始化
内置变量是否自动初始化,取决于该变量定义的位置。
①在全局范围内的或者静态局部内置类型变量均被编译器自动初始化为0值
②在函数体内定义的内置类型变量值随机 -
2、类类型变量的初始化
类类型变量是通过构造函数进行初始化的,不论类类型变量在哪里(全局或者局部)定义,该类类型变量的构造函数(默认构造函数或者指定的带参构造函数)总会被调用。
注意:
(1)对于内置类型变量(如int,double,bool等),如果定义在语句块外(即{}外),则变量被默认初始化为0;如果定义在语句块内(即{}内),变量将拥有未定义的值。
(2)对于类类型的变量(如string或其他自定义类型),不管定义于何处,都会执行默认构造函数。如果该类没有默认构造函数,则会引发错误。因此,建议为每个类都定义一个默认构造函数(=default)。
2、值初始化:值初始化是指使用了初始化器(即使用了圆括号或花括号)但却没有提供初始值的情况。
例如: int *p=new int();
3、直接初始化:直接初始化是指采用小括号的方式进行变量初始化(小括号里一定要有初始值,如果没提供初始值,那就是值初始化了!)。
例如:int a(0);
4、拷贝初始化:拷贝初始化是指采用等号(=)进行初始化的方式,编译器把等号右侧的初始值拷贝到新创建的对象中去。
例如: int a=1;
5、列表初始化:列表初始化是C++ 11 新引进的初始化方式,它采用一对花括号(即{})进行初始化操作。能用直接初始化和拷贝初始化的地方都能用列表初始化,而且列表初始化能对容器进行方便的初始化,因此在新的C++标准中,推荐使用列表初始化的方式进行初始化。列表初始化的应用场景有:int a{1};string s{“123”};vector vec{1,2,3};