在 C + + 中递增-什么时候使用 x + + 或 + + x?

我目前正在学习 C + + ,而且我已经学习了一段时间的增量。 我知道可以使用“ + + x”在前面进行增量,使用“ x + +”在后面进行增量。

尽管如此,我真的不知道什么时候使用这两种方法中的任何一种... 我从来没有真正使用过“ + + x”,到目前为止一切都很好——那么,我应该什么时候使用它呢?

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

另外,谁能准确地解释一下不同的增量(或减量)是如何工作的? 我真的很感激。

253767 次浏览

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

x++ increments the value of variable x 之后 processing the current statement.

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

So just decide on the logic you write.

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

Scott Meyers 告诉您选择前缀,除非在逻辑决定后缀是合适的情况下。

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

对于那些没有这本书的人,这里有一些相关的引言:

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

在第34页:

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

你正确地解释了区别。这取决于你想让 x 在每次循环之前或之后增加。这取决于你的程序逻辑,什么是合适的。

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

编辑: 修正了前缀和后缀表示法的混淆

我同意@BeowulfOF 的观点,不过为了清楚起见,我总是主张分开陈述,这样逻辑就绝对清楚了,比如:

i++;
x += i;

或者

x += i;
i++;

所以我的回答是,如果你写了清晰的代码,那么这应该很少有问题(如果有问题,那么你的代码可能不够清晰)。

只是想再次强调,+ + x 应该是 再快点而不是 x + + ,(特别是当 x 是任意类型的对象时) ,所以除非出于逻辑原因需要,否则应该使用 + + x。

递增迭代器时从 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   }

很明显,它的效率不如 前增量。

预增量不会生成临时对象。如果创建对象的代价很高,那么这会产生很大的不同。

我只是想注意,如果使用 pre/post 增量,生成的代码通常是相同的,而前/post 的语义并不重要。

例如:

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"

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

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

for (int i(0);i<10;++i)
for (int i(0);i<10;i++)

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

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

我们希望通过在字符串末尾遇到0字符(测试为 false)来执行循环。这需要在增量前测试值,并增量索引。但不一定是按照这个顺序——用前增量编写代码的方法是:

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

这是一个比较清晰的味道问题,如果机器有一把寄存器,那么两个寄存器的执行时间应该是相同的,即使[ i ]是一个昂贵的函数或者有副作用。一个显著的差异可能是索引的退出值。

后缀形式 + + ,——运算符遵循规则 使用-然后-改变,

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

Example 1:

当使用 Cout将多个值级联为 < < 时,则从右向左进行计算(如果有的话) ,但从左向右进行打印,例如(如果 Val最初为10)

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

会导致

12    10    10

例二:

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

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

它的输出在 Turbo C + + 将是

48 13

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

45 13
  • 注意: 对同一变量多次使用递增/递减运算符 不建议在一个表达式中使用
    表达式因编译器而异。

你要我举个例子:

这个(order是一个 std: : Vector)将在 order[i].size()访问时为 i == order.size()-1崩溃:

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

这将导致 没有order[i].size()崩溃,因为 i将被递增、检查并退出循环:

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

如果 count{5};

If you use ++count it will be process beforethe statement

total = --count +6;

总数等于10

如果您使用 count + + ,它将在语句之后进行处理

total = count-- +6;

总数等于11