豆瓣🔗:
- 英文版:Effective C++: 55 Specific Ways to Improve Your Programs and Designs
- 中文版:Effective C++: 改善程序与设计的55个具体做法
Effective C++
Scott Meyers
55 Specific Ways to Improve Your Programs and Designs
C++ 提供了4种不同又相辅相成的编程泛型(programming paradigms):
- procedural-based
- object-based
- object-oriented
- generics
Chapter 1: Accustoming Yourself to C++
1 View C++ as a federation of languages
C++: a multiparadigm programming language
- procedural
- object-oriented
- functional
- generic
- metaprogramming
C++’s four primary sublanguages:
- C
- Object-Oriented C++
- Template C++
- The STL
内置 (C-like) 类型:pass-by-value 通常比 pass-by-reference 高效。
从 C part of C++ 移往 Object-Oriented C++, 由于 用户自定义(user-defined) 构造函数和析构函数的存在,pass-by-reference-to-const 往往更好。 ——why?
For example, pass-by-value
is generally more efficient than pass-by-reference
for built-in (i.e., C-like) types, but when you move from the C part of C++ to Object-Oriented C++, the existence of user-defined constructors and destructors
means that pass-by-reference-to-const
is usually better. This is especially the case when working in Template C++
, because there, you don’t even know the type of object you’re dealing with. When you cross into the STL
, however, you know that iterators and function objects
are modeled on pointers in C
, so for iterator and function objects in the STL
, the old C pass-by-value
rule applied again.
Rules for effective C++ programming vary, depending on the part of C++ you are using.
2 Prefer consts, enums, and inlines to #defines
This item might better be called “Prefer the compiler to the preprocessor”.
|
|
- define constant pointers:
|
|
- class-specific constants: make it a static member
|
|
|
|
the values of an enumerated type can be used where ints are expected:
|
|
The enum hack:
It’s legal to take the address of a const, but it’s not legal to take the address of an enum and #define.
Also, through good compilers won’t set aside storage for const objects of integral types (unless you create a pointer or reference to the object), sloppy compilers may, and you may not be willing to set aside memory for such objects. Like enums, #defines never result in that kind of unnecessary memory allocation.
the enum back is a fundamental technique of template meta programming.
|
|
use a template for an inline function:
|
|
For simple constants, prefer const obejcts or enums to #defines.
For function-like macros, prefer inline functions to #defines.
3 use const whenever possible
|
|
When what’s pointed to is constant:
|
|
STL iterators:
- an iterator const: declare a pointer const (i.e., declaring a T* const pointer): the iterator isn’t allowed to point to something different, but the thing is points to may be modifed.
- a const_iterator: an iterator that points to something that can’t be modified (i.e., the STL analogue of const T* pointer)
|
|
|
|
const Member Functions
an important feature of C++: member functions differing only in their constness can be overloaded.
|
|
4 Make sure the objects are initialized before they’re used
|
|
|
|
It will often will be more efficient than above:
|
|
Singleton
|
|
|
|
Now the importance of initialzation order becomes apparent: unless tfs is initialized before tempDir, tempDir’s constructor will attempt use tfs before it’s been initialized. But tfs and tempDir were created by non-local static objects defined in different translation units. How can you be sure that tfs will be initialized before tempDir?
修改方法:local static对象替换non-local static对象,这是Singleton模式的一种常见实现手法。
|
|
Things to Remember
- Manually initialize objects of
built-in type
, because C++ only sometimes intializes them itself. - In a constructor, prefer use of the
member initialization list
toassignment inside the body of the constructor
. List data members in the initialization list in the same order they’re declared in the class. - Avoid initialization order problems across translation units by replacing
non-local static objects
withlocal static objects
.
Chapter 2: Constructors, Destructors, and Assignment Operators
5 Know what functions C++ silently writes and calls
|
|
6 Explicitly disallow the use of compiler-generated functions you do not want
|
|
改进方法:使用像Uncopyable这样的base class。
|
|
7 Declare destructors virtual in polymorphic base classes
|
|
修改方法:give the base class a virtual destructor. Deleting a derived class object will destroy the entire object, including all its derived class parts.
|
|
Things to Remember
Polymorphic base classes
should declare virtual destructors. If a class hasany virtual functions
, it should have a virtual destructor.- Classes not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors.
8 Prevent exceptions from leaving destructors
9 Never call virtual functions during construction or destruction
10 Have assignment operators return a reference to *this
11 Handle assignment to self in operator=
12 Copy all parts of an object
Chapter 3: Resource Management
13 Use objects to manage resources
14 Think carefully about copying behavior in resource-managing classes
15 Provide access to raw resources in resource-managing classes
16 Use the same form in corresponding uses of new and delete
17 Store need objects in smart pointers in standalone statements
Chapter 4: Designs and Declarations
18 Make interfaces easy to use correctly and hard to use incorrectly
|
|
wrapper types(外覆类型): (一直都不知道wrapper怎么翻译,这里这样翻译)
|
|
enum不具备类型安全性。
|
|
C++每个STL容器都有一个名为 size() 的成员函数。
Java:
- array:length property
- Strings: length method
- Lists: size method