一元算术运算符
有两种一元算术运算符:加号 (+) 和减号 (-)。提醒一下,一元运算符是只接受一个操作数的运算符。
运算符 | 符号 | 形式 | 操作 |
---|---|---|---|
一元加 | + | +x | x 的值 |
一元减 | - | -x | x 的负值 |
一元减运算符返回操作数乘以 -1 的值。换句话说,如果 x = 5,则 -x 为 -5。
一元加运算符返回操作数的值。换句话说,+5 是 5,+x 是 x。通常你不需要使用这个运算符,因为它是多余的。它主要是为了与一元减运算符对称而添加的。
为了可读性,这两个运算符都应该紧接在操作数之前(例如 -x
,而不是 - x
)。
不要将一元减运算符与使用相同符号的二元减法运算符混淆。例如,在表达式 x = 5 - -3;
中,第一个减号是二元减法运算符,第二个是一元减运算符。
二元算术运算符
有 5 种二元算术运算符。二元运算符是接受左操作数和右操作数的运算符。
运算符 | 符号 | 形式 | 操作 |
---|---|---|---|
加法 | + | x + y | x 加 y |
减法 | - | x - y | x 减 y |
乘法 | * | x * y | x 乘以 y |
除法 | / | x / y | x 除以 y |
取余 | % | x % y | x 除以 y 的余数 |
加法、减法和乘法运算符与现实生活中的工作方式相同,没有注意事项。
除法和取余需要一些额外的解释。我们将在下面讨论除法,在下一课中讨论取余。
整数和浮点数除法
最容易将除法运算符视为具有两种不同的“模式”。
如果操作数中的任何一个(或两个)是浮点值,则除法运算符执行浮点数除法。浮点数除法返回一个浮点值,并保留小数部分。例如,7.0 / 4 = 1.75
,7 / 4.0 = 1.75
,7.0 / 4.0 = 1.75
。与所有浮点数算术运算一样,可能会发生舍入误差。
如果两个操作数都是整数,则除法运算符执行整数除法。整数除法会舍弃任何小数部分并返回一个整数值。例如,7 / 4 = 1
,因为结果的小数部分被舍弃了。类似地,-7 / 4 = -1
,因为小数部分被舍弃了。
使用 static_cast<> 对整数执行浮点数除法
上面提出了一个问题——如果我们有两个整数,并且希望在不丢失小数的情况下进行除法,我们该怎么做?
在课程 4.12 — 类型转换和 static_cast 简介中,我们展示了如何使用 static_cast<> 运算符将字符转换为整数,使其作为整数而不是字符打印。
我们也可以类似地使用 static_cast<> 将整数转换为浮点数,以便我们可以执行浮点数除法而不是整数除法。考虑以下代码:
#include <iostream>
int main()
{
constexpr int x{ 7 };
constexpr 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;
}
这会产生结果
int / int = 1 double / int = 1.75 int / double = 1.75 double / double = 1.75
以上说明,如果任何一个操作数是浮点数,结果将是浮点数除法,而不是整数除法。
除以 0 和 0.0
除数为 0
的整数除法将导致未定义行为,因为结果在数学上是未定义的!
#include <iostream>
int main()
{
constexpr int apples { 12 };
std::cout << "You have " << apples << " apples. Enter how many people to divide them between: ";
int x {};
std::cin >> x;
std::cout << "Each person gets " << apples / x << " whole apples.\n"; // apples and x are int, so this is integer division
return 0;
}
如果您运行上述程序并输入 0
,您的程序很可能会崩溃。去试试吧,它不会损害您的电脑。
除以浮点值 0.0
的结果是实现定义的(意味着行为由编译器/架构决定)。在支持 IEEE754 浮点格式的架构上,结果将是 NaN
或 Inf
。在其他架构上,结果很可能是未定义行为。
相关内容
我们在 4.8 — 浮点数 课程中讨论 NaN
和 Inf
。
您可以通过运行以下程序并输入 0
或 0.0
来查看您的程序会做什么
#include <iostream>
int main()
{
constexpr int apples { 12 };
std::cout << "You have " << apples << " apples. Enter how many servings of apples you want: ";
double d {};
std::cin >> d;
std::cout << "Each serving is " << apples / d << " apples.\n"; // d is double, so this is floating point division
return 0;
}
算术赋值运算符
运算符 | 符号 | 形式 | 操作 |
---|---|---|---|
加法赋值 | += | x += y | 将 y 加到 x |
减法赋值 | -= | x -= y | 从 x 减去 y |
乘法赋值 | *= | x *= y | x 乘以 y |
除法赋值 | /= | x /= y | x 除以 y |
取余赋值 | %= | x %= y | 将 x / y 的余数放入 x |
到目前为止,当你需要给一个变量加 4 时,你很可能做了以下操作
x = x + 4; // add 4 to existing value of x
这可行,但有点笨拙,并且需要两个运算符才能执行(operator+ 和 operator=)。
因为像 x = x + 4
这样的语句非常常见,C++ 为了方便提供了五种算术赋值运算符。你不再需要写 x = x + 4
,你可以写 x += 4
。不再是 x = x * y
,你可以写 x *= y
。
因此,上面变成了
x += 4; // add 4 to existing value of x
修改和非修改运算符
能够修改其操作数之一值的运算符,非正式地称为修改运算符。在 C++ 中,大多数运算符都是非修改的——它们只是使用操作数来计算并返回一个值。但是,有两类内置运算符确实修改其左操作数(并返回值)
- 赋值运算符,包括标准赋值运算符 (
=
)、算术赋值运算符 (+=
、-=
、*=
、/=
和%=
),以及位赋值运算符 (<<=
、>>=
、&=
、|=
和^=
)。 - 增量和减量运算符(分别为
++
和--
)。我们将在 6.4 — 增量/减量运算符和副作用 课程中讨论这些。
此列表中不包括运算符 ==
、!=
、<=
和 >=
,因为这些是非修改的关系(比较)运算符(=
表示“等于”)。我们将在 6.7 — 关系运算符和浮点数比较 课程中讨论这些。
致进阶读者
重载运算符可以重新定义以具有与内置运算符不同的行为,这可能包括修改左操作数,即使内置版本不修改(反之亦然)。例如,用于输出的 operator<<
的重载版本会修改其左操作数(输出流对象)。