我想知道递增和递减运算符( ++ -- )是否比它的简单用途更有目的,以使代码更简单
也许:
i++;
比:
i = i + 1;
?
在许多方面,运算符的主要目的是向后兼容。在设计 C++ 时,一般规则是做 C 做的事情,至少对于非类类型;如果 C 没有++
and --
,我怀疑 C++ 会有它们。
当然,这引出了问题。无法想象它们会在现代编译器中生成不同的代码,而且委员会会出于优化原因引入它们是相当不可思议的(尽管您永远不知道——引入移动语义主要是出于优化原因)。但回到 1970 年代中期,在 C? 当时普遍认为,引入它们是因为它们对应于 PDP-11 上的机器指令。另一方面,它们已经存在于B中。C从B那里获得它们。而B是一种解释性语言,因此它们不存在对应于机器指令的问题。我自己的怀疑,这适用于许多运算符 ( &
,而不是and
等)是因为当时的开发主要是在电传打字机(tty's)上进行的,并且您输出到电传打字机的每个字符都会产生很多令人不快的噪音。所以你需要的字符越少越好。
至于++ i;
,i += 1;
和i = i + 1;
: 之间的选择,不必重复i
(当然,这可能是一个或多或少复杂的表达式)有一个明显的优势,所以你至少想要i += 1;
. Python 停在那里,如果没有其他原因,它将赋值视为语句,而不是任意表达式的副作用。在我使用 C 和 C++ 编程超过 30 年之后,我仍然觉得使用++ i
Python 编程时缺少这一点,尽管我在 C++ 中几乎将自己限制为将赋值视为语句(并且不要嵌入++ i
更复杂的表达式)。
您提供的两个示例几乎肯定会编译为完全相同的机器代码。编译器非常聪明。了解编译器很少执行您实际编写的代码。它会扭曲并塑造它以提高性能。任何现代编译器都会知道这一点i++;
并且i = i + 1;
是相同的(对于算术类型)并生成相同的输出。
但是,除了代码可读性之外,两者都有很好的理由。从概念上讲,多次增加一个值和增加一个值是不同的操作 - 它们在这里只是相同的,因为您要加 1。加法,例如x + 3
,是单个操作,而 do++++++x
表示具有相同效果的三个单独的操作。当然,聪明的编译器也会知道,对于算术类型的对象x
,它可以N
通过做 来在常数时间内做增量x + N
。
x
但是,如果是具有重载operator+
and的类类型,则编译器无法做出此假设operator++
。这两个运算符可能会做完全不同的事情。此外,将 an 实现operator+
为非常量时间操作会产生错误的印象。
当我们处理迭代器时,两者的重要性变得很明显。只有随机访问迭代器支持加法和减法。例如,标准原始指针是随机访问迭代器,因为您可以执行ptr + 5
并获取指向第 5 个对象的指针。但是,所有其他类型的迭代器(双向、前向、输入)不支持这一点 - 您只能增加它们(并减少双向迭代器)。要使用双向迭代器到达第 5 个元素,您需要执行++
5 次。那是因为加法表示一个恒定时间的操作,但许多迭代器根本无法在恒定时间内遍历。强制多个增量表明它不是一个恒定时间操作。
性能取决于i
.
如果它是内置类型,那么优化器将“注意到”您的两个语句是相同的,并为两者发出相同的代码。
由于您使用了后增量(并忽略了分号),因此即使i
是内置类型,这两个表达式也具有不同的值。的值i++
是旧值,的值i = i + 1
是新值。所以,如果你写:
j = i++;
k = (i = i + 1);
那么两者现在是不同的,并且两者都不会发出相同的代码。
由于后增量的后置条件与前增量相同,您可以说后增量运算符的主要目的是计算不同的值。无论性能如何,它都使语言更具表现力。
如果i
具有带有重载运算符的类类型,那么它可能不会那么简单。从理论上讲,这两者甚至可能没有相同的结果,但假设“明智的”运算符i + 1
返回该类的一个新实例,然后对其进行移动分配(在 C++11 中,如果该类型具有移动赋值运算符)或复制- (在 C++03 中)分配给i
. 无法保证优化器可以使此操作与实际操作一样高效operator++
,尤其是当运算符重载定义在另一个翻译单元中关闭时。
有些类型有operator++
但没有operator+
,例如std::list<T>::iterator
。但是,这不是存在的原因++
,因为它存在于 C 中,并且 C 没有类型 with ++
but not +
。这是 C++ 利用它现有的一种方式。
++
or运算符允许将--
其组合到其他语句中,而不是i=i+1
. 例如while (i++ < 10)
,允许进行 while 循环检查并在其后进行增量。用 是不可能的i=i+1
。
++
or--
运算符可以在其他类中重载以具有其他含义或通过其他操作进行增量和减量。请参阅此页面了解更多信息。
它们都不完全相同,尽管在功能上它们是相同的,但优先级i++
有所不同i=i+1
尝试在一些更复杂的表达式中替换 ++i 或 i++。您将在使用前增量/后增量功能时遇到困难。您将需要将表达式拆分为多个。这就像三元运算符。它是等效的,无论您输入代码的方式如何,编译器都可能会执行一些优化,但是三元运算符和前增量/后增量语法只是为您节省空间和代码的可读性。
两者都将通过体面的编译器在优化代码中生成相同的机器指令。
如果编译器认为i++
效率更高,那么它将转换i=i+1
为i++
,反之亦然。不管你写什么结果都是一样的。
我更喜欢++i
. 我从不写i=i+1
。
不,它只是让打字变得简单,让语法看起来更简单。
当它们都被编译时,它们被简化为相同的编译代码,并以相同的速度运行。
i++
和之间的区别在于i = i + 1
,第一个表达式只计算i
一次,而第二个表达式计算两次。考虑:
int& f() {
static int value = 0;
std::cout << "f() called\n";
return value;
}
f()++; // writes the message once
f() = f() + 1; // writes the message twice
如果f()
在不同的调用中返回不同的引用,这两个表达式会产生截然不同的效果。并不是说这是好的设计,当然……