考虑以下两个语句:
std::cout << "Hello world!";
int x { 5 };
“Hello world!“和5是什么?它们是字面量。字面量(也称为字面量常量)是直接插入到源代码中的固定值。
字面量和变量都有值(和类型)。与变量(其值可以通过初始化和赋值分别设置和更改)不同,字面量的值是固定的,不能更改。字面量5总是有值5。这就是为什么字面量被称为常量。
字面量与变量的区别
为了进一步强调字面量和变量之间的区别,让我们检查这个小程序:
#include <iostream>
int main()
{
std::cout << 5 << '\n'; // 打印字面量的值
int x { 5 };
std::cout << x << '\n'; // 打印变量的值
return 0;
}
在第5行,我们正在将值5打印到控制台。当编译器编译这个时,它将生成代码,使std::cout打印值5。这个值5被编译到可执行文件中,可以直接使用。
在第7行,我们创建了一个名为x的变量,并用值5初始化它。编译器将生成代码,将字面量值5复制到分配给x的内存位置。在第8行,当我们打印x时,编译器将生成代码,使std::cout打印x的内存位置的值(其值为5)。
因此,两个输出语句都做同样的事情(打印值5)。但在字面量的情况下,值5可以直接打印。在变量的情况下,值5必须从变量代表的内存中检索。
这也解释了为什么字面量是常量,而变量可以更改。字面量的值直接放在可执行文件中,可执行文件一旦创建就不能更改。变量的值放在内存中,内存的值可以在可执行文件运行时更改。
关键见解
字面量是直接插入到源代码中的值。这些值通常直接出现在可执行代码中(除非它们被优化掉)。 对象和变量代表持有值的内存位置。这些值可以根据需要检索。
相关内容 我们在第5.2课中更多地讨论字面量——字面量。
运算符基础
在数学中,操作是一个涉及零个或多个输入值(称为操作数)的过程,它产生一个新的值(称为输出值)。要执行的具体操作由一个称为运算符的符号表示。
例如,当我们还是孩子的时候,我们都学会了2 + 3等于5。在这种情况下,字面量2和3是操作数,符号+是运算符,它告诉我们对操作数应用数学加法以产生新值5。
C++中的运算符
在C++中,操作正如你所期望的那样工作。例如:
#include <iostream>
int main()
{
std::cout << 1 + 2 << '\n';
return 0;
}
在这个程序中,字面量1和2是加号(+)运算符的操作数,它产生了输出值3。然后这个输出值被打印到控制台。在C++中,操作的输出值通常被称为返回值。
你很可能已经非常熟悉数学中常用的标准算术运算符,包括加法(+)、减法(-)、乘法(*)和除法(/)。在C++中,赋值(=)也是一个运算符,插入(«)、提取(»)和相等(==)也是如此。虽然大多数运算符都有符号名称(例如+或==),但也有许多运算符是关键字(例如new、delete和throw)。
出于我们将在更详细讨论运算符时变得清晰的原因,对于符号运算符,通常将运算符的符号附加到"运算符"这个词上。 例如,加号运算符将被写为operator+,提取运算符将被写为operator»。
运算符的元数
运算符接受的操作数数量称为运算符的元数。很少有人知道这个词的意思,所以不要在对话中使用它,期望有人知道你在说什么。C++中的运算符有四种不同的元数:
一元运算符作用于一个操作数。一元运算符的一个例子是-运算符。例如,给定-5,operator-取字面量操作数5并翻转其符号以产生新的输出值-5。
二元运算符作用于两个操作数(通常称为左和右,因为左操作数出现在运算符的左侧,右操作数出现在运算符的右侧)。二元运算符的一个例子是+运算符。例如,给定3 + 4,operator+取左操作数3和右操作数4并应用数学加法以产生新的输出值7。插入(«)和提取(»)运算符是二元运算符,左侧取std::cout或std::cin,右侧取要输出的值或要输入的变量。
三元运算符作用于三个操作数。C++中只有一个这样的运算符(条件运算符),我们将在后面介绍。
零元运算符作用于零个操作数。C++中也只有一个这样的运算符(throw运算符),我们也将在后面介绍。
请注意,一些运算符根据它们的使用方式有多个含义。例如,operator-有两个上下文。它可以用作一元形式来反转数字的符号(例如,将5转换为-5,或反之),或者它可以用作二元形式进行减法(例如,4 - 3)。
链接运算符
运算符可以链接在一起,使得一个运算符的输出可以用作另一个运算符的输入。例如,给定以下情况:2 * 3 + 4,乘法运算符首先执行,并将左操作数2和右操作数3转换为返回值6(成为加号运算符的左操作数)。接下来,加号运算符执行,并将左操作数6和右操作数4转换为新值10。
我们将在深入讨论运算符的主题时,进一步讨论运算符执行的顺序。现在,只需知道算术运算符的执行顺序与标准数学中的顺序相同:首先括号,然后指数,然后乘法和除法,然后加法和减法。这个顺序有时缩写为PEMDAS,或扩展为助记符"请原谅我亲爱的阿姨莎莉”。
返回值和副作用
大多数C++中的运算符只使用它们的操作数来计算返回值。例如,-5产生返回值-5,2 + 3产生返回值5。有一些运算符不产生返回值(例如delete和throw)。我们将在后面介绍这些运算符的作用。
一些运算符有额外的行为。一个运算符(或函数)如果除了产生返回值之外还有可观察的效果,就被认为是有副作用的。例如,x = 5有将值5分配给变量x的副作用。即使在运算符执行完毕后,x的值变化也是可观察的(例如,通过打印x的值)。std::cout « 5有将5打印到控制台的副作用。即使在std::cout « 5执行完毕后,我们也可以观察到5已经被打印到控制台上。
术语解释
在通用语言中,“副作用"一词通常用来表示其他事情发生时的次要(通常是负面或意外的)结果(例如,服用药物)。例如,口服抗生素的一个常见副作用是腹泻。因此,我们通常认为副作用是我们想要避免的,或者是主要目标的附带事项。
在C++中,“副作用"这个术语有不同的含义:它是运算符或函数除了产生返回值之外的可观察效果。
由于赋值有改变对象值的可观察效果,这被认为是副作用。我们主要使用某些运算符(例如赋值运算符)来实现它们的副作用(而不是这些运算符产生的返回值)。在这种情况下,副作用既是有益的,也是可以预测的(通常是返回值才是附带的)。
运算符的返回值
对于我们主要为了它们的返回值而调用的运算符(例如operator+或operator*),它们的返回值通常是什么(例如,操作数的和或积)是显而易见的。
对于我们主要为了它们的副作用而调用的运算符(例如operator=或operator«),它们产生的返回值(如果有的话)并不总是显而易见的。例如,你期望x = 5有什么返回值?
operator=和operator«(当用于将值输出到控制台时)都返回它们的左操作数。因此,x = 5返回x,std::cout « 5返回std::cout。这样做是为了使这些运算符可以链接。
例如,x = y = 5评估为x = (y = 5)。首先y = 5将5分配给y。这个操作然后返回y,然后可以分配给x。
std::cout « “Hello " « “world!“评估为(std::cout « “Hello “) « “world!"。这首先将"Hello “打印到控制台。这个操作返回std::cout,然后可以用来将"world!“打印到控制台。