0.引用
1.INDEX

Chapter 25: WrITING EFFICIENT C++ 881
Overview of Performance and Efficiency 882
Two Approaches to Efficiency 882
Two Kinds of Programs 882
Is C++ an Inefficient Language? 882
Language-Level Efficiency 883
Handle Objects Efficiently 884
Pass-by-Reference 884
Return-by-Reference 886
Catch Exceptions by Reference 886
Use Move Semantics 886
Avoid Creating Temporary Objects 886
The Return-Value Optimization 887
Pre-allocate Memory 888
Use Inline Methods and Functions 888
Design-Level Efficiency 889
Cache Where Necessary 889
Use Object Pools 890
An Object Pool Implementation 891
Using the Object Pool 893
Profiling 894
Profiling Example with gprof 895
First Design Attempt 895
Profiling the First Design Attempt 898
Second Design Attempt 900
Profiling the Second Design Attempt 901
Profiling Example with Visual C++ 2017 902
Summary 907
2. OVERVIEW OF PERFORMANCE AND EFFICIENCY
Before delving further into the details, it’s helpful to define the terms performance
and efficiency,as used in this book. The performance of a program can refer to several
areas, such as speed,memory usage, disk access, and network use. This chapter focuses
on speed performance. The term efficiency, when applied to programs, means running
without wasted effort. An efficient program completes its tasks as quickly as possible
within the given circumstances. A program can be efficient without being fast, if the
application domain is inherently prohibitive to quick execution. Note that the title
of this chapter, “Writing Efficient C++,” means writing programs that run efficiently,
not efficiently writing programs. That is, the time you learn to save by reading this
chapter will be your users’, not your own!
NOTE An efficient, or high-performance, program runs as fast as is possible for
the particular tasks.
2.1 Two Approaches to Efficiency
Language-level efficiency involves using the language as efficiently as possible, for example, pass-
ing objects by reference instead of by value. However, this will only get you so far. Much more
important is design-level efficiency, which includes choosing efficient algorithms, avoiding unneces-
sary steps and computations, and selecting appropriate design optimizations. More often than not,
optimizing existing code involves replacing a bad algorithm or data structure with a better, more
efficient one.
2.2 Two Kinds of Programs
As I’ve noted, efficiency is important for all application domains. Additionally,
there is a small subset of programs, such as system-level software, embedded
systems, intensive computational applications, and real-time games, that require
extremely high levels of efficiency. Most programs don’t.Unless you write those
types of high-performance applications, you probably don’t need to worry about
squeezing every ounce of speed out of your C++ code. Think of it as the difference
between building normal family cars and building sports cars. Every car must be
reasonably efficient, but sports cars require extremely high performance. You
wouldn’t want to waste your time optimizing family cars for speed when they’ll
never go faster than 70 miles per hour.
2.3 Is C++ an Inefficient Language?
C programmers often resist using C++ for high-performance applications. They claim that the
language is inherently less efficient than C or a similar procedural language because C++
includes high-level concepts, such as exceptions and virtual methods. However, there
are problems with this argument.
When discussing the efficiency of a language, you must separate the performance
capabilities of the language itself from the effectiveness of its compilers at
optimizing it, that is, you cannot ignore the effect of compilers. Recall that
the C or C++ code you write is not the code that the computer executes. A compiler
first translates that code into machine language, applying optimizations in the
process. This means that you can’t simply run benchmarks of C and C++ programs and
compare the results. You’re really comparing the compiler optimizations of the
languages, not the languages themselves. C++ compilers can optimize away many of the
high-level constructs in the language to generate machine code similar to, or even
better than, the machine code generated from a comparable C program. These days, much
more research and development is poured into C++ compilers than into C compilers, so
C++ code might actually get better optimized and might run faster than C code.
Critics, however, still maintain that some features of C++ cannot be optimized away.
For example,as Chapter 10 explains, virtual methods require the existence of a vtable
and an additional level of indirection at run time, possibly making them slower than
regular non-virtual function calls. However, when you really think about it, this
argument is unconvincing. Virtual method calls provide more than just a function call:
they also give you a run-time choice of which function to call.
A comparable non-virtual function call would need a conditional statement to decide
which function to call. If you don’t need those extra semantics, you can use a
non-virtual function. A general design rule in the C++ language is that “if you don’t
use a feature, you don’t need to pay for it.” If you don’t use virtual methods, you
pay no performance penalty for the fact that you could use them. Thus, non-virtual
function calls in C++ are identical to function calls in C in terms of
performance.However, because virtual function calls have such a tiny overhead, I
recommend making all your class methods, including destructors but not constructors,
virtual for all your non-final classes.
Far more important, the high-level constructs of C++ enable you to write cleaner
programs that are more efficient at the design level, are more readable, more easily
maintained, and avoid accumulating unnecessary and dead code.
I believe that you will be better served in your development, performance, and
maintenance by choosing C++ instead of a procedural language such as C.
There are also other higher-level object-oriented languages such as C# and Java, both
of which run on top of a virtual machine. C++ code is executed directly by a CPU;
there is no such thing as a virtual machine to run your code. C++ is closer to the
hardware, which means that in most cases it runs faster than languages such as C#
and Java.
3.LANGUAGE-LEVEL EFFICIENCY
Many books, articles, and programmers spend a lot of time trying to convince you to apply language-
level optimizations to your code. These tips and tricks are important, and can speed up your programs
in some cases. However, they are far less important than the overall design and algorithm choices in
your program. You can pass-by-reference all you want, but it won’t make your program fast if you per-
form twice as many disk writes as you need to. It’s easy to get bogged down in references and pointers
and forget about the big picture.
Furthermore, some of these language-level tricks can be performed automatically by good optimiz-
ing compilers. You should never spend time optimizing a particular area, unless a profiler, discussed
later in this chapter, tells you that that particular area is a bottleneck.
That being said, using certain language-level optimizations, such as pass-by-reference, is just consid-
ered good coding style.
In this book, I’ve tried to present a balance of strategies. So, I’ve included here what I feel are the
most useful language-level optimizations. This list is not comprehensive, but is a good start to write
optimized code. However, make sure to read, and practice, the design-level efficiency advice that I
offer later in this chapter as well.
WARNING Apply language-level optimizations judiciously. I recommend making a clean,
well-structured design and implementation first. Then use a profiler,
and only invest time optimizing those parts that are flagged by a profiler as being
a performance bottleneck.
3.1
本文探讨了C++与C语言的效率问题,指出C++并非效率低的语言,高效的C++代码主要依赖于设计层面的优化,如选择合适的数据结构和算法,而非仅仅关注语言层面的技巧。文章强调了正确使用语言特性如引用、异常处理和内存预分配等对提高效率的重要性,并提供了关于程序设计和性能分析的建议。
986

被折叠的 条评论
为什么被折叠?



