前缀或后缀自增(或自减)的使用
Usage of prefix or postfix increment (or decrement)
我发现这段代码是c++书籍(c++ Primer, 5th Edition)中逗号操作符使用的一个例子:
vector<int>::size_type cnt = ivec.size();
// assign values from size...1 to the elements in ivec
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)
ivec[ix] = cnt;
我认为这不是一个合适的例子,因为计算的顺序和副作用在这里并不重要。逗号操作符只允许分隔自增和自减表达式,这是逗号操作符的常用用法,但不是本书本节的目的。cppreference.com显示了一个更好的例子(请向下滚动到标题内置逗号操作符)。
我真正想到的是下面的练习:
本节中的程序使用了前缀自增和自减操作符。解释为什么我们使用前缀而不是后缀。要使用后缀必须做哪些更改版本?使用后置操作符重写程序。
在这种情况下,没有特别的理由选择前缀操作符而不是后缀操作符。求值顺序并不重要。对simple
类型的对象(如vector<int>::size_type
)的操作在实践中不应该从使用前缀而不是后缀中受益,因此为了性能问题,使用前缀而不是后缀只是一种已知的惯例。
为了给你完整的背景,这里是书中的部分:
4.10逗号算子
逗号操作符接受两个操作数,从左到右求值。就像逻辑上的AND AND逻辑或和条件运算符,逗号运算符保证其操作数的求值顺序。左边的表达式被求值,其结果被丢弃。逗号表达式的结果是其右侧的值表达式。如果右操作数为an,则结果为左值左值。逗号操作符的一种常见用法是在for循环中:
vector<int>::size_type cnt = ivec.size(); // assign values from size...1 to the elements in ivec for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt) ivec[ix] = cnt;
该循环对表达式in中的ix递增,对cnt递减for标头。ix和cnt在每次穿越时都要更改循环。只要ix的测试成功,我们就重置
下一个当前元素到的当前值。
我说的对吗?还是我不明白这个练习的目的?
你是对的,在这个例子中使用前缀或后缀递增运算符并不重要,但是 c++ Primer也说只有在真正必要的时候才使用后缀版本作为最佳实践,我引用了§4.5的书。自增和自减运算符
建议:仅在必要时使用后缀操作符
具有C背景的读者可能会对我们在编写的程序中使用前缀自增感到惊讶。原因很简单:前缀版本避免了不必要的工作。它将值递增并返回递增的版本。后缀操作符必须存储原始值,以便返回未加1的值作为结果。如果不需要未加1的值,则不需要后缀操作符所做的额外工作。对于
int
和指针,编译器可以优化掉这些额外的工作。对于更复杂的迭代器类型,这些额外的工作可能会更昂贵。通过习惯性地使用前缀版本,我们不必担心性能差异是否重要。而且,也许更重要的是,我们可以更直接地表达程序的意图。
- 高效的字符串截断算法,按顺序删除相等的前缀和后缀
- 为什么 C++ 程序员更喜欢前缀 ++,而 Java 程序员更喜欢后缀 ++?
- 导致错误的后缀和前缀增量
- 为什么后缀增量比C 中的前缀更快
- C++编译器如何扩展前缀和后缀运算符++()?
- 指向重载前缀和后缀运算符中的类对象的指针
- C++如何知道在重载运算符时增量++是前缀或后缀
- 在一行C 中,该代码后缀和前缀的输出的逻辑是什么
- Android Cmake编译器正在生成带有额外前缀和符号后缀的.out文件
- 为什么后缀失败并且前缀在传递迭代器作为参数并在尾部位置递归时工作正常
- std::map<tuple<int,int>.lower_bound/upper_bound 前缀搜索,而不找到后缀的最小/最大元素
- 在迭代器上澄清后缀/前缀操作员
- 前缀和后缀运算符 C++
- 在哪里可以找到C++11类型前缀/后缀的列表
- 编译器如何翻译后缀/前缀运算符
- 为什么所有type_traits类都必须使用 'typename' 和'::type'前缀/后缀调用?
- 涡轮增压C++(非可视)(后缀和前缀运算符)
- ++ 后缀和前缀的起源
- C++后缀/前缀运算符重载作为非成员函数
- 使用C/ c++将后缀/前缀表达式显示为解析树