提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
开始
一、基础
左值和右值
在C++11中所有的值必属于左值、右值两者之一。在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值。举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址;表达式b+c、函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名找到它,&(b+c)这样的操作则不会通过编译。
左值/右值表达式:当一个对象被用作右值,指的是对象的值(内容),被用作左值时,指的是对象的身份(在内存中的位置)。
求值顺序
优先级规定运算对象的组合方式,但并没有说明运算对象求值顺序(除了与(&&),或(||),条件(?:)和逗号(,)运算符四种)。如:
int i = f1()*f2();
f1与f2会在执行乘法前被调用,但是无法知道f1还是f2先被调用。
所以,在表达式指向并修改同一个对象时,将发生未定义的行为,如:
int i = 0;
cout << i << " " << ++i << endl; //未定义行为
此时,我们无法意料编译器最后输出的结果,它可能是01,也可能是11,甚至其它结果。
二、算数运算符
包括+、-、*、/、%(求余数),需要注意溢出的情况,如16位的short类型最大位32767.
C++中%和/均向0取整.
m%(-n)等于m%n,(-m)%n等于-(m%n),如:
21%6 //=3
-21%-8 //=-5
21%-5 //=1
三、逻辑和关系运算符
if(val) {}; //如果val非0,条件为真
本节练习
#include<iostream>
using namespace std;
int main() {
int i;
cin >> i;
while (i != 42)
cin >> i;
}
四、赋值运算符
左侧必须为可修改的左值:
1024 = k //错误,1024为右值
可以用列表进行赋值:
int k = 0;
k = {5}; //正确
k = {3.14}; //错误,不能类型转化
与其它运算符不同,赋值运算满足右结合律:
int ival,jval;
jval = ival = 0; //正确
五、递增和递减运算符
即++与–:
int i = 0,j = 0;
cout << ++i << endl; //输出i=1;
cout << i++ << endl; //输出i=0;
常与*混用:
cout << *iter++ << endl; //输出iter指向的对象并向前移动一位
大多数运算符没有说明运算对象求值顺序,所以避免如下情况:
*beg = toupper(*beg++); //错误,编译器可能先计算左侧*beg,也可能先计算右侧*beg++
六、成员访问运算符
ptr->mem等价于(*ptr).mem。
七、条件运算符
cond?expr1:expr2.真执行expr1,假执行expr2。
string finalgrade = (grade<60)?"fail" :"pass";
条件运算符优先级较低。
本节练习
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> vec{ 1,2,3,4 };
for (auto& a : vec) {
a = a * ((a % 2 == 0) ? 1 : 2);
cout << a << ' ';
}
}
八、位运算符
将对象看作二进制计算。
九、sizeof运算符
计算表达式或者类型名字所占字节数
本节练习
#include<iostream>
#include<vector>
using namespace std;
int main() {
int x[10]; int* p = x; int i = 1;
cout << sizeof(x) / sizeof(*x) << endl;
cout << sizeof(p) / sizeof(*p) << endl;
cout << sizeof(x) << endl;
}
十、逗号运算符
十一、类型转换
本节练习
#include<iostream>
int main() {
int iv = 3.5 + 3.52;
std::cout << iv << std::endl;
}