对于运算符,需要了解他们的工作内容,优先级,和顺序。比如+
号是从左到右x =((3 + 4)+ 5)
,=
号是从右到左x =(y = z)
。
运算符的汇总、优先级、作用顺序如下表所示:
如果表达式不是特别明显,推荐使用括号来表示他们的先后运算关系
算术运算符
一元运算符
-x
表示把x变成负数,这是一个专门的一元运算符,中间不能加空格。
1 - -2
就等价于1 - (-2)
。
二元运算符
就是常规的“加减乘除、求余数”。需要注意的是除法和求余数,涉及整数和小数两种不同的除法。
小数除法:
如果操作数中的任何一个(或两个)是浮点值,则除法运算符执行浮点除法。 浮点除法返回浮点值,并保留分数。例如,7.0 / 4 = 1.75和 7 / 4.0 = 1.75,和7.0 / 4.0 = 1.75。与所有浮点算术运算一样,可能会发生舍入错误。
整数除法:
整数除法删除任何分数并返回整数值。例如,7 / 4 = 1因为结果的小数部分被丢弃。同样,-7 / 4 = -1因为小数部分被丢弃。
如果不想整数发生舍弃误差,可以通过static_cast <>
将其中一个整数变成小数。
如:
#include <iostream>
int main()
{
int x{ 7 };
int y{ 4 };
std::cout << "int / int = " << x / y << "\n";
std::cout << "double / int = " << static_cast<double>(x) / y << "\n";
std::cout << "int / double = " << x / static_cast<double>(y) << "\n";
std::cout << "double / double = " << static_cast<double>(x) / static_cast<double>(y) << "\n";
return 0;
}
求余数
-6 % 4 = -2
6 % -4 = 2
余数一直跟被除数保持一致。
余数可以用来判断是否能被整除,比如是否是偶数。
指数运算
C++没有专门定义的指数运算符,可以通过math库里面的函数实现该功能。
比如:
#include <cmath>
pow(3.0, 4.0); // 3 to the 4th power
pow
函数产生的结果是double
类型,所以如果想要一个整型的结果,转数据类型,可能会发生精度损失的问题。
提供一个整型求指数的写好的函数,可以直接调用:
#include <iostream>
#include <cstdint> // for std::int_fast64_t
// note: exp must be non-negative
std::int_fast64_t powint(int base, int exp)
{
std::int_fast64_t result{ 1 };
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
int main()
{
std::cout << powint(7, 12); // 7 to the 12th power
return 0;
}
递增/递减操作符
符号前置的就是简单给x增加1,后置的是给x加1,但是返回加1前的x。
具体看例子:
#include <iostream>
int main()
{
int x{ 5 };
int y{ 5 };
std::cout << x << " " << y << '\n';
std::cout << ++x << " " << --y << '\n'; // prefix
std::cout << x << " " << y << '\n';
std::cout << x++ << " " << y-- << '\n'; // postfix
std::cout << x << " " << y << '\n';
return 0;
}
最后的输出是:
5 5
6 4
符号前置,返回加1后的x
6 4
6 4
符号后置,返回的是加1前的值,所以不变,但是x已经被改变
7 3
!!注意:
它会永久性改变x的值,所以一定要小心,比如下面的情况:
int add(int x, int y)
{
return x + y;
}
int main()
{
int x{ 5 };
int value = add(x, ++x); // is this 5 + 6, or 6 + 6?
// It depends on what order your compiler evaluates the function arguments in
std::cout << value; // value could be 11 or 12, depending on how the above line evaluates!
return 0;
}
条件运算符
是if...else...
的一种压缩写法,比如:
if (x > y)
larger = x;
else
larger = y;
可以写成:
larger = (x > y) ? x : y;
注意事项:
①x和y必须是同一种数据类型
②?
和:
的优先级非常非常地低,因此要及时加括号,防止产生意外情况。
std::cout << (x > y) ? x : y;
实际等价于(std::cout << (x > y)) ? x : y;
。
适用情况:
当我们需要变量的条件初始化器(或赋值)或将条件值传递给函数时,它最有用。
比如初始化某个常数变量时:
#include <iostream>
int main()
{
bool inBigClassroom { false };
const int classSize { inBigClassroom ? 30 : 20 };
std::cout << "The class size is: " << classSize;
return 0;
}
这个不能使用if...else...
语句做,因为if...else...
中产生的变量是局部变量,当变量结束时就会销毁。
#include <iostream>
int main()
{
bool inBigClassroom { false };
if (inBigClassroom)
const int classSize { 30 };
else
const int classSize { 20 };
std::cout << "The class size is: " << classSize;
return 0;
}
这一段代码就会报错,因为classSize
会随着if...else...
语句销毁。
关系运算符
逻辑运算符
非运算
需要注意运算优先级,非运算的优先级非常高,比如! x < y
,等价于(! x) < y
。
并运算、或运算的短路评估
并运算:如果左边是False,则右边的直接不计算。
或运算:如果左边是False,则右边的直接不计算。
对于这样的代码:
if (x == 1 && ++y == 2)
如果x !=1
,则右边的++y
永远不会被运算,这点需要注意。