在C ++中增加 – 何时使用x ++或++ x?

我目前正在学习C ++,而前一段时间我也学习了这个增量。 我知道你可以使用“++ x”来使之前的增量和“x ++”来完成。

不过,我真的不知道什么时候使用这两种…我从来没有真正使用过“++ x”,而且到目前为止,事情一直很好 – 所以,我应该什么时候使用它?

例如:在for循环中,何时最好使用“++ x”?

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

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

处理当前语句 x++递增variablesx的值。

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

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

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

斯科特·迈尔斯(Scott Meyers)告诉你更喜欢前缀(prefix),除非在逻辑上指定后缀是合适的地方。

“更有效的C ++”项目#6 – 这对我来说是足够的权威。

对于那些不拥有这本书的人来说,这里有相关的引语。 从页面32:

从你作为C程序员的日子,你可能会记得增量操作符的前缀forms有时被称为“增量和取”,而后缀forms通常被称为“取和增量”。 这两个短语很重要,因为它们都只是作为正式的规范。

和在页34:

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

从递增迭代器时的cppreference :

如果你不打算使用旧的值,你应该更喜欢pre-increment操作符(++ 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 } 

显然,它比预增量效率低。

预增量不会生成临时对象。 如果您的对象创build昂贵,这可以产生显着的差异。

我只是想要注意到,如果你使用前/后增量(pre / 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需要在增量实际发生之前返回值 – 因此,它必须创build对象的临时副本(预增量)。 这比++ x更有效,它在原地增加并返回。

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

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

我同意@BeowulfOF,尽pipe为了清楚起见,我总是主张分裂陈述,以便逻辑是绝对清楚的,即:

 i++; x += i; 

要么

 x += i; i++; 

所以我的答案是,如果你写清楚的代码,那么这应该很less(如果它很重要,那么你的代码可能不够清楚)。

只是想再次强调,++ x预计会比x ++ 更快 (特别是如果x是某种任意types的对象),所以除非出于逻辑的原因需要使用++ x。

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

处理STL-Iterator(也实现这些操作符)的一个重要区别是,它会创build迭代器指向的对象的副本,然后递增,然后返回副本。 ++另一方面先执行增量,然后返回对迭代器现在指向的对象的引用。 当性能的每一点都计数或者当你实现你自己的STL迭代器时,这大部分是相关的。

编辑:修正前缀和后缀符号的混合

在考虑代码的清晰度时,理解语言的语法很重要。 考虑复制一个string,例如后增加:

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

我们希望循环通过遇到string末尾的零字符(它testing错误)来执行。 这就要求testing值的预增量和增加索引。 但不一定按照这种顺序 – 用预增量编码的方法是:

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

这是一个味道更清楚的问题,如果机器有一个寄存器,那么即使一个[i]是一个昂贵的或有副作用的函数,它们也应该有相同的执行时间。 指数的退出价值可能有显着差异。

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

前缀forms(++ x, – x)遵循规则更改 – 然后使用

例1:

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

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

将导致进入

 12 10 10 

例2:

在Turbo C ++中,如果在expression式中发现多个++或(以任何forms),则首先计算所有前缀forms,然后计算expression式,最后计算后缀forms,

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

这是在Turbo C ++的输出

 48 13 

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

 45 13 
  • 注:不build议在一个expression式中多次使用相同variables的递增/递减运算符。 这样的处理/结果
    expression式因编译器而异。