110

我目前正在学习 C++,不久前我已经了解了增量。我知道您可以使用“++x”在之前进行增量,然后使用“x++”进行增量。

不过,我真的不知道什么时候使用这两者中的任何一个......我从来没有真正使用过“++x”并且到目前为止一切都很好 - 那么,我应该什么时候使用它呢?

示例:在 for 循环中,什么时候最好使用“++x”?

另外,有人可以准确解释不同的增量(或减量)是如何工作的吗?我真的很感激。

4

12 回答 12

150

这不是偏好问题,而是逻辑问题。

x++在处理当前语句增加变量 x 的值。

++x在处理当前语句之前增加变量 x 的值。

所以只要决定你写的逻辑。

x += ++i将增加 i 并将 i+1 添加到 x。 x += i++将 i 添加到 x,然后增加 i。

于 2009-11-28T16:47:38.547 回答
56

Scott Meyers告诉您更喜欢前缀,除非在逻辑要求后缀合适的情况下。

“更有效的 C++”项目 #6 - 这对我来说已经足够权威了。

对于那些不拥有这本书的人,这里是相关的引文。从第 32 页开始:

在您作为 C 程序员的日子里,您可能还记得增量运算符的前缀形式有时被称为“增量和获取”,而后缀形式通常被称为“获取和增量”。记住这两个短语很重要,因为它们几乎都是正式的规范......

在第 34 页:

如果你是那种担心效率的人,当你第一次看到后缀增量函数时,你可能会大汗淋漓。该函数必须为其返回值创建一个临时对象,并且上面的实现还创建了一个必须构造和销毁的显式临时对象。前缀增量函数没有这样的临时...

于 2009-11-28T16:49:50.853 回答
30

递增迭代器时来自cppreference :

如果您不打算使用旧值,您应该更喜欢前增量运算符 (++iter) 而不是后增量运算符 (iter++)。后增量一般是这样实现的:

   Iter operator++(int)   {
     Iter tmp(*this); // store the old value in a temporary object
     ++*this;         // call pre-increment
     return tmp;      // return the old value   }

显然,它的效率低于预增量。

预增量不会生成临时对象。如果您的对象的创建成本很高,这可能会产生重大影响。

于 2009-11-28T16:57:42.087 回答
8

我只想注意,如果您使用前/后增量,而语义(前/后)无关紧要,则生成的代码是相同的。

例子:

pre.cpp:

#include <iostream>

int main()
{
  int i = 13;
  i++;
  for (; i < 42; i++)
    {
      std::cout << i << std::endl;
    }
}

post.cpp:

#include <iostream>

int main()
{

  int i = 13;
  ++i;
  for (; i < 42; ++i)
    {
      std::cout << i << std::endl;
    }
}

_

$> g++ -S pre.cpp
$> g++ -S post.cpp
$> diff pre.s post.s   
1c1
<   .file   "pre.cpp"
---
>   .file   "post.cpp"
于 2009-11-28T17:19:55.163 回答
6

imo 要记住的最重要的事情是,x++ 需要在实际发生增量之前返回值——因此,它必须制作对象的临时副本(预增量)。这比 ++x 效率低,后者在原地递增并返回。

不过,另一件值得一提的事情是,大多数编译器将能够尽可能优化这些不必要的东西,例如,这两个选项都会导致相同的代码:

for (int i(0);i<10;++i)
for (int i(0);i<10;i++)
于 2009-11-28T22:56:09.233 回答
5

我同意@BeowulfOF,但为了清楚起见,我总是主张拆分陈述,以便逻辑绝对清晰,即:

i++;
x += i;

或者

x += i;
i++;

所以我的回答是,如果您编写清晰的代码,那么这应该很少有关系(如果很重要,那么您的代码可能不够清晰)。

于 2009-11-28T16:57:03.897 回答
2

只是想再次强调 ++x 预计比 x++(特别是如果 x 是某个任意类型的对象),因此除非出于逻辑原因需要,否则应使用 ++x。

于 2009-11-28T16:57:10.493 回答
2

++,-- 运算符的后缀形式遵循规则use-then-change

前缀形式 (++x,--x) 遵循规则change-then-use

示例 1:

当多个值与 << 使用cout级联时,计算(如果有)从右到左进行,但打印从左到右进行,例如,(如果最初为 10则为val )

 cout<< ++val<<" "<< val++<<" "<< val;

将导致

12    10    10 

示例 2:

在 Turbo C++ 中,如果在一个表达式中多次出现 ++ 或(以任何形式),则首先计算所有前缀形式,然后计算表达式,最后计算后缀形式,例如,

int a=10,b;
b=a++ + ++a + ++a + a;
cout<<b<<a<<endl;

它在 Turbo C++ 中的输出将是

48 13

而它在现代编译器中的输出将是(因为它们严格遵守规则)

45 13
  • 注意:不建议在一个表达式中对同一变量多次使用递增/递减运算符。此类表达式的处理/结果
    因编译器而异。
于 2015-11-07T07:27:31.363 回答
2

如果count{5};

如果你使用 ++count 它将在语句之前处理

total = --count +6;

总计将等于 10

如果你使用 count++ 它将在语句之后处理

total = count-- +6;

总计将等于 11

于 2021-09-16T09:15:37.613 回答
1

您正确解释了差异。这仅取决于您是否希望 x 在每次运行循环之前或之后递增。这取决于您的程序逻辑,什么是合适的。

处理 STL 迭代器(也实现了这些运算符)时的一个重要区别是,it++ 创建迭代器指向的对象的副本,然后递增,然后返回副本。另一方面,++it 首先进行增量,然后返回对迭代器现在指向的对象的引用。当每一点性能都很重要或当您实现自己的 STL 迭代器时,这主要是相关的。

编辑:修复了前缀和后缀符号的混淆

于 2009-11-28T16:51:30.943 回答
1

你问了一个例子:

这 ( orderis a std::vector) 将i == order.size()-1order[i].size()访问时崩溃:

while(i++ < order.size() && order[i].size() > currLvl);

不会在 处崩溃order[i].size(),因为i会增加、检查并退出循环:

while(++i < order.size() && order[i].size() > currLvl);
于 2021-03-19T20:59:03.890 回答
0

在考虑代码的清晰度时,理解语言语法很重要。考虑复制字符串,例如使用后增量:

char a[256] = "Hello world!";
char b[256];
int i = 0;
do {
  b[i] = a[i];
} while (a[i++]);

我们希望通过在字符串末尾遇到零字符(测试为假)来执行循环。这需要测试值预增量并增加索引。但不一定按这个顺序 - 一种用预增量编码的方法是:

int i = -1;
do {
  ++i;
  b[i] = a[i];
} while (a[i]);

这是一个更清楚的口味问题,如果机器有几个寄存器,两者都应该具有相同的执行时间,即使 a[i] 是一个昂贵或有副作用的函数。一个显着的差异可能是指数的退出值。

于 2014-11-02T16:34:39.087 回答