<Item 1>View C++ as a federation of languages。

1、把C++看成4种子语言组成,即C、Object-Oriented C++、Template C++、The STL。

2、Things to Remember:Rules for effective C++ programming vary, depending on the part of C++ you are using.

因为C++有很多的编程范式,在项目开发过程中,明确规范怎么使用C++很重要,这样可以使整个团队尽量使用一样的风格,并把项目一直做下去

 <Item 2>Prefer consts, enums, and inlines to #defines。

3、prefer the compiler to the preprocessor。因为宏定义不会被编译到符号表里面去,因此会对问题的调试定位带来麻烦,同时宏定义不能进行面向对象的封装和私有化。

4、使用常量代替宏定义的时候需要注意两个点,

一个是定义指针常量的时候需要使用两个const,如

const char * const authorName = "Scott Meyers";

其中前一个const修饰char,后一个const修饰指针,可以逆着读authorName 是一个const指针,指向const的char常量

另一个是使用class-specific constant的时候,为了保持一个内存copy,需要使用static进行定义

 class GamePlayer {
private:
static const int NumTurns = ; // constant declaration
int scores[NumTurns]; // use of constant
...
};

What you see above is a declaration for NumTurns, not a definition. Usually, C++ requires that you provide a definition for anything you use, but class-specific constants that are static and of integral type (e.g., integers, char s, bool s) are an exception. As long as you don't take their address, you can declare them and use them without providing a definition. If you do take the address of a class constant, or if your compiler incorrectly insists on a definition even if you don't take the address, you provide a separate definition like this:

const int GamePlayer::NumTurns; // definition of NumTurns; see // below for why no value is given

Because the initial value of class constants is provided where the constant is declared (e.g., NumTurns is initialized to 5 when it is declared), no initial value is permitted at the point of definition.(也可以声明的时候不给初值,而在定义的时候给初值)

Note, by the way, that there's no way to create a class-specific constant using a #define, because #define s don't respect scope.

5、the enum hack

 class GamePlayer {
private:
enum { NumTurns = }; // "the enum hack" — makes
// NumTurns a symbolic name for 5
int scores[NumTurns]; // fine
...
};

First, the enum hack behaves in some ways more like a #define than a const does, and sometimes that's what you want. For example, it's legal to take the address of a const, but it's not legal to take the address of an enum, and it's typically not legal to take the address of a #define, either. If you don't want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint.

A second reason to know about the enum hack is purely pragmatic. Lots of code employs it, so you need to recognize it when you see it. In fact, the enum hack is a fundamental technique of template metaprogramming

6、another common (mis)use of the #define directive is using it to implement macros that look like functions but that don't incur the overhead of a function call.

  // call f with the maximum of a and b

 #define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

替换为

 template<typename T> // because we don't
inline void callWithMax(const T&a,const T&b)// know what T is, we
{ // pass by reference-to-
f(a > b ? a : b); // const — see Item 20
}

7、Given the availability of const s, enum s, and inline s, your need for the preprocessor (especially #define) is reduced, but it's not eliminated. #include remains essential, and #ifdef /#ifndef continue to play important roles in controlling compilation. It's not yet time to retire the preprocessor, but you should definitely give it long and frequent vacations.

8、Things to Remember:

 For simple constants, prefer const objects or enums to #define s.
 For function-like macros, prefer inline functions to #define s.

<Item 3>Use const whenever possible。

9、const施加了一个semantic constraint,并有编译器来保证,同时It allows you to communicate to both compilers and other programmers that a value should remain invariant.

10、下面两种语法格式含义一致都表示Widget 为const常量

 void f1(const Widget *pw); // f1 takes a pointer to a
// constant Widget object
void f2(Widget const *pw); // so does f2

11、If you want an iterator that points to something that can't be modified (i.e., the STL analogue of a const T* pointer), you want a const_iterator :

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

12、Having a function return a constant value often makes it possible to reduce the incidence of client errors without giving up safety or efficiency.

 class Rational {... };
const Rational operator*(const Rational& lhs, const Rational& rhs);
Rational a, b, c;
...
(a * b) = c; // invoke operator= on the
// result of a*b!
if (a * b = c)... // oops, meant to do a comparison!

13、The purpose of const on member functions is to identify which member functions may be invoked on const objects. Such member functions are important for two reasons. First, they make the interface of a class easier to understand. It's important to know which functions may modify an object and which may not. Second, they make it possible to work with const objects. That's a critical aspect of writing efficient code, because, as Item 20 explains, one of the fundamental ways to improve a C++ program's performance is to pass objects by reference-to-const. That technique is viable only if there are const member functions with which to manipulate the resulting const -qualified objects.

14、Many people overlook the fact that member functions differing only in their constness can be overloaded, but this is an important feature of C++.const objects most often arise in real programs as a result of being passed by pointer- or reference-to-const.

15、What does it mean for a member function to be const ? There are two prevailing notions: bitwise constness (also known as physical constness) and logical constness.The bitwise const camp believes that a member function is const if and only if it doesn't modify any of the object's data members (excluding those that are static), i.e., if it doesn't modify any of the bits inside the object.In fact, bitwise constness is C++'s definition of constness, and a const member function isn't allowed to modify any of the non-static data members of the object on which it is invoked.(对象中包含指针的时候,指针不变但是指针指向的数据可变)。Adherents to this philosophy argue that a const member function might modify some of the bits in the object on which it's invoked, but only in ways that clients cannot detect.mutable frees non-static data members from the constraints of bitwise constness:

class CTextBlock {
public:
...
std::size_t length() const;
private:
char *pText;
mutable std::size_t textLength; // these data members may
mutable bool lengthIsValid; // always be modified, even in
}; // const member functions
std::size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); // now fine
lengthIsValid = true; // also fine
}
return textLength;
}

16、Avoiding Duplication in const and Non-const Member Functions

class TextBlock {
public:
...
const char& operator[](std::size_t position) const // same as before {
...
...
...
return text[position];
}
char& operator[](std::size_t position) // now just calls const op[]
{ return const_cast<char&>( // cast away const on
// op[]'s return type;
static_cast<const TextBlock&>(*this) // add const to *this's type;
[position] // call const version of op[]
);
}
...
};

16、Things to Remember

 Declaring something const helps compilers detect usage errors. const can be applied to objects at any 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.
 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 4> Make sure that objects are initialized before they're used

17、The rules of C++ stipulate that data members of an object are initialized before the body of a constructor is entered.参数初始化列表才是真实的初始化过程,构造函数内部的赋值不是初始化。For objects of built-in type like numTimesConsulted, there is no difference in cost between initialization and assignment, but for consistency, it's often best to initialize everything via member initialization.

18、Sometimes the initialization list must be used, even for built-in types. For example, data members that are const or are references must be initialized; they can't be assigned

19、当有很多成员或者基类需要初始化的时候,it's not unreasonable to omit entries in the lists for data members where assignment works as well as true initialization, moving the assignments to a single (typically private) function that all the constructors call.

20、One aspect of C++ that isn't fickle is the order in which an object's data is initialized. This order is always the same: base classes are initialized before derived classes (see also Item 12), and within a class, data members are initialized in the order in which they are declared.  成员初始化的顺序和初始化列表中的顺序无关,但是建议初始化列表中的数据和声明的顺序一致,以免读者误解

21、A static object is one that exists from the time it's constructed until the end of the program. Stack and heap-based objects are thus excluded. Included are global objects, objects defined at namespace scope, objects declared static inside classes, objects declared static inside functions, and objects declared static at file scope. Static objects inside functions are known as local static objects (because they're local to a function), and the other kinds of static objects are known as non-local static objects. Static objects are automatically destroyed when the program exits, i.e., their destructors are automatically called when main finishes executing.

22、A translation unit is the source code giving rise to a single object file. It's basically a single source file, plus all of its #include files.

23、The problem we're concerned with, then, involves at least two separately compiled source files, each of which contains at least one non-local static object (i.e., an object that's global, at namespace scope, or static in a class or at file scope). And the actual problem is this: if initialization of a non-local static object in one translation unit uses a non-local static object in a different translation unit, the object it uses could be uninitialized, because the relative order of initialization of non-local static objects defined in different translation units is undefined.解决方案是使用函数封装static变量确保初始化。This approach is founded on C++'s guarantee that local static objects are initialized when the object's definition is first encountered during a call to that function.

class FileSystem { ... };           // as before
FileSystem& tfs() // this replaces the tfs object; it could be
{ // static in the FileSystem class
static FileSystem fs; // define and initialize a local static object
return fs; // return a reference to it } class Directory { ... }; // as before
Directory::Directory( params ) // as before, except references to tfs are
{ // now to tfs()
...
std::size_t disks = tfs().numDisks(); //使用函数封装确保初始化
...
} Directory& tempDir() // this replaces the tempDir object; it
{ // could be static in the Directory class
static Directory td; // define/initialize local static object
return td; // return reference to it
}

24、On the other hand, the fact that these functions contain static objects makes them problematic in multithreaded systems. Then again, any kind of non-const static object — local or non-local — is trouble waiting to happen in the presence of multiple threads. One way to deal with such trouble is to manually invoke all the reference-returning functions during the single-threaded startup portion of the program. This eliminates initialization-related race conditions.

25、Things to Remember
 Manually initialize objects of built-in type, because C++ only sometimes initializes them itself.
 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.
 Avoid initialization order problems across translation units by replacing non-local static objects with local static objects.

<Effective C++>读书摘要--Accustoming Youself to C++的更多相关文章

  1. <Effective C++>读书摘要--Implementations<二>

    <Item29> Strive for exception-safe code. 1.如下面的代码 class PrettyMenu { public: ... void changeBa ...

  2. <Effective C++>读书摘要--Implementations<一>

    1.For the most part, coming up with appropriate definitions for your classes (and class templates) a ...

  3. <Effective C++>读书摘要--Designs and Declarations<一>

    <Item 18> Make interfaces easy to use correctly and hard to use incorrectly 1.That being the c ...

  4. <Effective C++>读书摘要--Introduction

    Introduction 1.Learning the fundamentals of a programming language is one thing; learning how to des ...

  5. <Effective C++>读书摘要--Templates and Generic Programming<一>

    1.The initial motivation for C++ templates was straightforward: to make it possible to create type-s ...

  6. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>

    <Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...

  7. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<一>

    1.Furthermore, I explain what the different features in C++ really mean — what you are really expres ...

  8. <Effective C++>读书摘要--Designs and Declarations<三>

    <Item 22> Declare data members private 1.使数据成员private,保持了语法的一致性,client不会为访问一个数据成员是否需要使用括号进行函数调 ...

  9. <Effective C++>读书摘要--Designs and Declarations<二>

    <Item 20> Prefer pass-by-reference-to-const to pass-by-value 1.By default, C++ passes objects ...

随机推荐

  1. 在WIN7下安装运行mongodb

    1).下载MongoDB http://downloads.mongodb.org/win32/mongodb-win32-i386-2.4.5.zip 下载Windows 32-bit版本并解压缩, ...

  2. ueditor 富文本编辑器 Uncaught TypeError: Cannot set property 'innerHTML' of undefined问题

    ueditor.addListener("ready", function () { ueditor.setContent(‘内容'); });

  3. A64 I2S调试

    通过A64 的I2S总线与回音消除模块连接,在A64中需要使能并配置daudio功能. Daudio 为A64 的数字音频接口,可配置成i2s/pcm格式标准音频接口. 内核配置在lichee/lin ...

  4. python 两个面试题

    1.下面程序的运算结果是什么?? class Parent: def func(self): print("In Parent func") def __init__(self): ...

  5. flask(列表数据接口设计)

    新闻列表数据只是当前页面的一部分 点击分类时需要去获取当前分类下的新闻数据 并在展示的时候需要更新新闻列表界面,不需要整体页面刷新 所以新闻数据也使用 ajax 的方式去请求后台接口进行获取 接口设计 ...

  6. mfc和qt的区别

    注:引用来源 http://wenda.chinabaike.com/b/30934/2013/1208/707410.html QT使用的编译器是MinGW,即Linux下的GCC移植到window ...

  7. Java学习笔记十六:Java中的构造方法

    Java中的构造方法 1.使用new+构造方法 创建一个新的对象: 2.构造方法是定义在Java类中的一个用来初始化对象的方法: 3.构造方法与类同名且没有返回值: 4.语法格式: public 构造 ...

  8. JZ2440开发板:UART(串口)使用(学习笔记)

    查看UART在硬件上的信息,阅读JZ2440原理图可以看到: JZ2440开发板的UART0是可以跟USB相接的,用于打印调试,UART1,UART2两个串口用来外接模块.所以本文仅对UART0进行操 ...

  9. WinSCP与Putty远程连接linux

    1.  有时putty连接不上,可能是linux机器上的telnet服务未开,把蓝线上的√去掉. 2. ctrl + p 打开putty窗口: 3. putty如果显示乱码,右键 putty窗口,选择 ...

  10. 链表--数据结构与算法JavaScript描述(6)

    链表 概念 链表是由一组节点组成的集合. 每个节点都使用一个对象的引用指向它的后继. 指向另一个节点的引用叫做 链. 许多链表的实现都在链表最前面有一个特殊节点,叫做头节点. 链表的尾元素指向一个nu ...