您的位置:首页 > 编程语言 > C语言/C++

Effective C++读书笔记

2015-12-07 23:27 363 查看
Item 1

1. For simple constants, prefer const objects or enums to #define s.

2. For function-like macros, prefer inline functions to #define s.

Item 2

Use const whever possible

有关iterator比较容易弄错的地方

const  std::vector<int>::iterator iter = vec.begin  //iter acts like a T* const
*iter = 10; //OK, changes what iter points to
++iter; //error! iter is const


std::vector<int>::const_iterator cIter = vec.begin(); //cIter acts like a const T*
*cIter = 10; //error! *cIter is const
++cIter; //fine, changes cIter


一些函数返回const值,可以避免一些可能的错误。如下:

class Rational {... };
const Rational operator*(const Rational& lhs, const Rational& rhs);
Rational a, b, c;
...
(a * b) = c;  //这种错误就可以避免了.


const Member Functions

Overloaded const member function, 例如

class TextBlock
{
public:
...
const char& operator[](std::size_t position) const
{
return text[position]; //operator[] for const
//objects
}
char& operator[](std::size_t position)
{
return text[position]; //operator[] for
//non-const objects
}
private:
std::string text;


Declaring something
const
helps compilers detect usage errors.
const
can be applied to objects at an scope, to function parameters and return types, and to member functions as a whole.

Compilers enforce bitwise constness, but you should program using conceptual constness(use
mutable
)

When
const
and non-
const
member functions have essentially identical implementations, code duplication can be avoided by having the non-
const
version call the const version.

Item 3

1. Manually initialize objects of built-in type, because C++ only sometimes initializes them itself.

2. In a constructor, prefer use of the member initialization list to assignment inside the body of the constructor. List data members in the initialization list in the same order they’re declared in the class.

3. Avoid initialization order problems across translation units by replacing non-local static objects with local static objects.

Item 4

1. Compilers may implicitly generate a class’s default constructor, copy constructor, copy assignment operator, and destructor.

2. To disallow functionality automatically provided by compilers, declare the corresponding member functions private and give no implementations. Using a base class like
Uncopyable
is one way to do this

Item 5

1. Polymorphic base classes should declare virtual destructors. If a class has any virtual functions, it should have a virtual destructor.

2. Classed not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors.

Item 6

1. Destructors should never emit exceptions. If functions called in a destructor may throw, the destructor should catch any exceptions, then swallow or terminate the program.

2. If class clients need to be able to react to exceptions thrown during an operation, the class should provide a regular(i.e., non-destructor) function that performs the operation.

Item 7

Don’t call virtual functions during construction or destruction, because such calls will never go to a more derived class than that of the currently executing constructor or destructor.

Item 8

Have assignment operators return a reference to *this.

Item 9

1. Make sure operator= is well-behaved when an object is assigned to itself. Techniques include comparing addresses of source and target objects, careful statment ordering, and copy-and-swap.

2. Make sure that any function operating on more than one object behaves correctly if two of more of the objects are the same.

Item 10

1. Copying functions should be sure to copy all of an object’s data members and all of its base class parts.

2. Don’t try to implement one of the copying functions in terms of the other. Instead, put common functionality in a third function that both call.

Item 11

1. To prevent resource leaks, use RAII(Resource Acquisition Is Initialization) objects that acquire resource in their constructors and release them in their destructors.

2. Two commonly useful RAII classed are
TR1::shared_ptr
and
auto_ptr
;
tr1::shared_ptr
is usually the better choice because its behavior when copied is intuitive. Copying an
auto_ptr
sets it to null.

Item 12

1. APIs often require access to raw resources, so each RAII class should offer a way to get at the resource it manages.

2. Access may be via explicit conversion or implicit conversion. In general, explicit conversion is safer, but implicit conversion is more convenient for clients.

Item 13

If you use
[]
in a
new
expression, you must use
[]
in the corresponding expression. If you don’t use
[]
in a
new
expression, you mustn’t use
[]
in the corresponding
delete
expression.

Item 14

Store
new
ed objects in smart pointers in standalone statements. Failure to do this can lead to subtle resource leaks when exceptions are thrown.

Item 15

1. Good interfaces are easy to use and hard to use incorrectly. Your should strive for these characteristics in all your interfaces.

2. Ways to facilitate correct use include consistency in interfaces and behavioral compatibility with built-in types.

3. Ways to prevent errors include creating new types, restricting operations on types, constraining object values, and eliminating client resource management responsibilities.

4.
TR1::shared_ptr
supports custom deleters. This prevents the cross-DLL problem, can be used to automatically unlock mutexes, etc.

Item 16

1. How should objects of your new type be created and detroyed?

2. How should object initialization differ from object assignment?

3. What does it mean for objects of your new type to be passed by value?

4. What are the restrictions on legal values for your new type?

5. Does your new type fit into an inheritance graph?

6. What kind of type conversions are allowed for your new type?

7. What operators and functions make sense for the new type?

8. What should have access to the members of your new type?

9. What is the “undeclared interface” of your new type?

10. How general is your new type?

11. Is a new type really what you need?

Item 17

1. Prefer pass-by-reference-to-const over pass-by-value. It’s typically more efficient and it avoids the slicing problem.

2. The rule doesn’t apply to built-in types and STL iterator and function object types. For them, pass-by-value is usually appropriate.

Item 18

Never return a pointer or reference to a local stack object, a reference to a heap-allocated object, or a pointer or reference to a local static object if there is a chance that more than one such object will be needed.

Item 19

1. Declare data members private. It gives clients syntactically uniform access to data, affords fine-grained access control, allows invariants to be enforced, and offers class authors implementation flexibility.

2.
protected
is no more encapsulated than
public


Item 20

Prefer non-member non friend functions to member functions. Doing so increases encapsulation, packaging flexibility, and functional extensibility.

Item 21

If you need type conversions on all parameters to a function(including the one pointed to by the this pointer), the function must be a non-member.(比如一些二目运算符)

Item 22

1. Provide a
swap
member function when
std::swap
would be inefficient for your type . Make sure your
swap
doesn’t throw exceptions.

2. If you offer a member
swap
, also offer a non-member
swap
that calls the member. For classed(not templates), specialize
std::swap
, too.

3. When calling
swap
, employ a
using
declaration for
std::swap
, then call
swap
without namespace qualification.

4. It’s fine to totally specialize
std
templates for user-defined types, but never try to add something completely new to
std
.

Item 23

Postpone variable definitions as long as possible. It increases program clarity and improves program efficiency.

Item 24

class Window
{
public:
virtual void OnSize() {... }
};

class SpecialWindow : public Window
{
public:
virtual void OnSize()
{
static_cast<Window>(*this).OnSize(); //wrong
//way to call
//base method
Window::OnSize(); //the right way
}
};


static_cast(*this).OnSize()会创建一个临时的对象,所做的操作也是在这个临时对象上的。

Avoid casts whenever practical, especially
dynamic_cast
s in performance-sensitive code. If a design requires casting, try to develop a cast-free alternative.

When casting is necessary, try to hide it inside a function. Clients can then call the function instead of putting casts in their own code.

Prefer C++-style casts to old-style casts. They are easier to see, and they are more specific about what they do.

(未完待续…)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: