我目前正在学习 C++,不久前我已经了解了增量。我知道您可以使用“++x”在之前进行增量,然后使用“x++”进行增量。
不过,我真的不知道什么时候使用这两者中的任何一个......我从来没有真正使用过“++x”并且到目前为止一切都很好 - 那么,我应该什么时候使用它呢?
示例:在 for 循环中,什么时候最好使用“++x”?
另外,有人可以准确解释不同的增量(或减量)是如何工作的吗?我真的很感激。
我目前正在学习 C++,不久前我已经了解了增量。我知道您可以使用“++x”在之前进行增量,然后使用“x++”进行增量。
不过,我真的不知道什么时候使用这两者中的任何一个......我从来没有真正使用过“++x”并且到目前为止一切都很好 - 那么,我应该什么时候使用它呢?
示例:在 for 循环中,什么时候最好使用“++x”?
另外,有人可以准确解释不同的增量(或减量)是如何工作的吗?我真的很感激。
这不是偏好问题,而是逻辑问题。
x++
在处理当前语句后增加变量 x 的值。
++x
在处理当前语句之前增加变量 x 的值。
所以只要决定你写的逻辑。
x += ++i
将增加 i 并将 i+1 添加到 x。
x += i++
将 i 添加到 x,然后增加 i。
Scott Meyers告诉您更喜欢前缀,除非在逻辑要求后缀合适的情况下。
“更有效的 C++”项目 #6 - 这对我来说已经足够权威了。
对于那些不拥有这本书的人,这里是相关的引文。从第 32 页开始:
在您作为 C 程序员的日子里,您可能还记得增量运算符的前缀形式有时被称为“增量和获取”,而后缀形式通常被称为“获取和增量”。记住这两个短语很重要,因为它们几乎都是正式的规范......
在第 34 页:
如果你是那种担心效率的人,当你第一次看到后缀增量函数时,你可能会大汗淋漓。该函数必须为其返回值创建一个临时对象,并且上面的实现还创建了一个必须构造和销毁的显式临时对象。前缀增量函数没有这样的临时...
递增迭代器时来自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.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 效率低,后者在原地递增并返回。
不过,另一件值得一提的事情是,大多数编译器将能够尽可能优化这些不必要的东西,例如,这两个选项都会导致相同的代码:
for (int i(0);i<10;++i)
for (int i(0);i<10;i++)
我同意@BeowulfOF,但为了清楚起见,我总是主张拆分陈述,以便逻辑绝对清晰,即:
i++;
x += i;
或者
x += i;
i++;
所以我的回答是,如果您编写清晰的代码,那么这应该很少有关系(如果很重要,那么您的代码可能不够清晰)。
只是想再次强调 ++x 预计比 x++快(特别是如果 x 是某个任意类型的对象),因此除非出于逻辑原因需要,否则应使用 ++x。
++,-- 运算符的后缀形式遵循规则use-then-change,
前缀形式 (++x,--x) 遵循规则change-then-use。
当多个值与 << 使用cout级联时,计算(如果有)从右到左进行,但打印从左到右进行,例如,(如果最初为 10则为val )
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
如果count{5};
如果你使用 ++count 它将在语句之前处理
total = --count +6;
总计将等于 10
如果你使用 count++ 它将在语句之后处理
total = count-- +6;
总计将等于 11
您正确解释了差异。这仅取决于您是否希望 x 在每次运行循环之前或之后递增。这取决于您的程序逻辑,什么是合适的。
处理 STL 迭代器(也实现了这些运算符)时的一个重要区别是,it++ 创建迭代器指向的对象的副本,然后递增,然后返回副本。另一方面,++it 首先进行增量,然后返回对迭代器现在指向的对象的引用。当每一点性能都很重要或当您实现自己的 STL 迭代器时,这主要是相关的。
编辑:修复了前缀和后缀符号的混淆
你问了一个例子:
这 ( order
is a std::vector) 将i == order.size()-1
在order[i].size()
访问时崩溃:
while(i++ < order.size() && order[i].size() > currLvl);
这不会在 处崩溃order[i].size()
,因为i
会增加、检查并退出循环:
while(++i < order.size() && order[i].size() > currLvl);
在考虑代码的清晰度时,理解语言语法很重要。考虑复制字符串,例如使用后增量:
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] 是一个昂贵或有副作用的函数。一个显着的差异可能是指数的退出值。