C/C++——++i、i+=1、i++之间的区别(附在学习boost时遇到的例子)
来源:互联网 发布:哪里有卖校管家软件 编辑:程序博客网 时间:2024/06/05 11:42
首先,对于++i和i++的区别是早就认识到了,效率肯定是前置++i更高,因为后者还需要产生临时变量。
查了相关资料
其实这个问题可以从三个角度去分析:语言规范,编译器实现,CPU支持。首先从语言规范上来讲;前置++和后置++是不等价的,前置++在规范中明确指出 和+=组合操作符是等价的,但和E = E+1;这样的赋值操作不等价,因为后者对操作数E需要进行两次求值,而+=组合操作符只进行一次求值。后置++表示操作数作为结果值被获取之后操作数的 原值再进行更新。 聪明的编译器可以根据应用场景进行优化(标准不规定相关优化的手段,由编译器自决),但不能过度依赖这种优化,因为编译器还是不如人聪明,而且复杂的表达式也不一定可以优化掉。从 CPU的角度上来讲CPU支持什么样的指令集是绝对决定了相应操作符计算效率。在嵌入式开发中不同的CPU之间的差异就大了。比如说PowerPC CPU就没有直接可以对应后缀++的t自增指令,某些版本的ARM CPU没有任何自增指令(无论是前置还是后置式的)。因此无论从CPU支持来讲还是编译器优化来看前置++肯定是高效的,后置++的即时CPU和编译器优化都支持也不能比前置++更高效,在使用的时候应该尽量使用前置++。C/C++提供这么多操作符是因为它是最接近底层的高级语言,它需要尽可能实现CPU对应 指令的高级实现进而为性能优化提供选择。而其它多数高级语言不会给你选择的权利。
下面是标准中的相关信息:
The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation. The expression ++E is equivalent to (E+=1).
See the discussions of additive operators and compound assignment for information on
constraints, types, side effects, and conversions and the effects of operations on pointers.
The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.) See the discussions of additive operators and compound assignment
for information on constraints, types, and conversions and the effects of operations on
pointers. The side effect of updating the stored
A compound assignment of the form E1 op= E2 differs from the simple assignment
expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.
来看具体例子
这个是我写的cpp文件
#include <boost\progress.hpp>#include <iostream>#include <vector>#include <fstream>using namespace boost;using namespace std;int main(){ vector<string> v(100); ofstream fs("./test.txt"); //声明一个progress_display对象,基数是v的大小 progress_display pd(v.size()); //开始迭代遍历向量,处理字符串,写入文件 for (auto& x : v){ fs << x << endl; ++pd; } return 0;}
下面是progress_display.hpp
// boost progress.hpp header file ------------------------------------------//// Copyright Beman Dawes 1994-99. Distributed under the Boost// Software License, Version 1.0. (See accompanying file// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)// See http://www.boost.org/libs/timer for documentation.// Revision History// 1 Dec 01 Add leading progress display strings (suggested by Toon Knapen)// 20 May 01 Introduce several static_casts<> to eliminate warning messages// (Fixed by Beman, reported by Herve Bronnimann)// 12 Jan 01 Change to inline implementation to allow use without library// builds. See docs for more rationale. (Beman Dawes) // 22 Jul 99 Name changed to .hpp// 16 Jul 99 Second beta// 6 Jul 99 Initial boost version#ifndef BOOST_PROGRESS_HPP#define BOOST_PROGRESS_HPP#include <boost/timer.hpp>#include <boost/noncopyable.hpp>#include <boost/cstdint.hpp> // for uintmax_t#include <iostream> // for ostream, cout, etc#include <string> // for stringnamespace boost {// progress_timer ----------------------------------------------------------//// A progress_timer behaves like a timer except that the destructor displays// an elapsed time message at an appropriate place in an appropriate form.class progress_timer : public timer, private noncopyable{ public: explicit progress_timer( std::ostream & os = std::cout ) // os is hint; implementation may ignore, particularly in embedded systems : timer(), noncopyable(), m_os(os) {} ~progress_timer() { // A) Throwing an exception from a destructor is a Bad Thing. // B) The progress_timer destructor does output which may throw. // C) A progress_timer is usually not critical to the application. // Therefore, wrap the I/O in a try block, catch and ignore all exceptions. try { // use istream instead of ios_base to workaround GNU problem (Greg Chicares) std::istream::fmtflags old_flags = m_os.setf( std::istream::fixed, std::istream::floatfield ); std::streamsize old_prec = m_os.precision( 2 ); m_os << elapsed() << " s\n" // "s" is System International d'Unites std << std::endl; m_os.flags( old_flags ); m_os.precision( old_prec ); } catch (...) {} // eat any exceptions } // ~progress_timer private: std::ostream & m_os;};// progress_display --------------------------------------------------------//// progress_display displays an appropriate indication of // progress at an appropriate place in an appropriate form.// NOTE: (Jan 12, 2001) Tried to change unsigned long to boost::uintmax_t, but// found some compilers couldn't handle the required conversion to double.// Reverted to unsigned long until the compilers catch up. class progress_display : private noncopyable{ public: explicit progress_display( unsigned long expected_count_, std::ostream & os = std::cout, const std::string & s1 = "\n", //leading strings const std::string & s2 = "", const std::string & s3 = "" ) // os is hint; implementation may ignore, particularly in embedded systems : noncopyable(), m_os(os), m_s1(s1), m_s2(s2), m_s3(s3) { restart(expected_count_); } void restart( unsigned long expected_count_ ) // Effects: display appropriate scale // Postconditions: count()==0, expected_count()==expected_count_ { _count = _next_tic_count = _tic = 0; _expected_count = expected_count_; m_os << m_s1 << "0% 10 20 30 40 50 60 70 80 90 100%\n" << m_s2 << "|----|----|----|----|----|----|----|----|----|----|" << std::endl // endl implies flush, which ensures display << m_s3; if ( !_expected_count ) _expected_count = 1; // prevent divide by zero } // restart unsigned long operator+=( unsigned long increment ) // Effects: Display appropriate progress tic if needed. // Postconditions: count()== original count() + increment // Returns: count(). { if ( (_count += increment) >= _next_tic_count ) { display_tic(); } return _count; } unsigned long operator++() { return operator+=( 1 ); } unsigned long count() const { return _count; } unsigned long expected_count() const { return _expected_count; } private: std::ostream & m_os; // may not be present in all imps const std::string m_s1; // string is more general, safer than const std::string m_s2; // const char *, and efficiency or size are const std::string m_s3; // not issues unsigned long _count, _expected_count, _next_tic_count; unsigned int _tic; void display_tic() { // use of floating point ensures that both large and small counts // work correctly. static_cast<>() is also used several places // to suppress spurious compiler warnings. unsigned int tics_needed = static_cast<unsigned int>((static_cast<double>(_count) / static_cast<double>(_expected_count)) * 50.0); do { m_os << '*' << std::flush; } while ( ++_tic < tics_needed ); _next_tic_count = static_cast<unsigned long>((_tic/50.0) * static_cast<double>(_expected_count)); if ( _count == _expected_count ) { if ( _tic < 51 ) m_os << '*'; m_os << std::endl; } } // display_tic};} // namespace boost#endif // BOOST_PROGRESS_HPP
- C/C++——++i、i+=1、i++之间的区别(附在学习boost时遇到的例子)
- ++i和i++的区别(C++)
- C语言笔记——(i++)和(++i)的区别
- i += 1; i++; ++i的区别
- 【C++】i++跟++i的区别
- 【c++】i++和++i的区别
- 【c语言】i++和++i的区别
- 【C/C++学习】之十二、++i与i++的区别
- linux c一站式学习 ++i和i++的区别
- [C++]关于i++和++i的学习
- [C++]关于i++和++i的学习
- [C++]关于i++和++i的学习
- [C++]关于i++和++i的学习
- i++和++i和i+=1之间的区别(效率)
- i=i+1 i++ ++I的区别
- i=i+1 i++ ++I的区别?
- ++i与i++的区别(c++primer)
- JAVA/C#中神奇的i=i++/i--,完全区别于C/C++
- AndroidStudio导入jar包
- 序: Android 系统架构学习 概述
- Recyclerview+checkbox
- stm32 pwm输出异常及解决过程
- Linux--apache日志分割脚本
- C/C++——++i、i+=1、i++之间的区别(附在学习boost时遇到的例子)
- redis jar包下载地址
- 面试题5: 从尾到头打印链表
- 4.2.4--广搜--A strange lift
- 隐藏的BUG探讨——从“Y2K”问题到“2038”年问题
- 最小差
- Spark 提升spark1.6提交任务速度+配置spark2.x后hiveserver2运行失败
- UML图绘制,理论学习
- 4.2.3--广搜--Rescue