<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. tp5.1路由报错No input file specified.

    问题: 按照官方教安装了框架,打开首页没问题,可是安装教程路由规则打开 "http://127.0.0.1/hello/2" 时, 却报错误  "No input fil ...

  2. 基于Geomesa服务查询轨迹数据无法根据空间和时间范围进行结果查询

    一.Geomesa - QuickStart(教程工程包)   百度网盘下载地址:geomesa-tutorials-master.7z 二.解压后,IDEA编译如下 百度网盘下载地址:IDEA201 ...

  3. rails应用中各数据平台的对接

    1.mongo #Gemfile添加如下两个gem包gem 'mongoid', '~> 5.1.0' gem 'mongo', '~> 2.4’ @client = Mongo::Cli ...

  4. Java学习笔记二十八:Java中的接口

    Java中的接口 一:Java的接口: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承 ...

  5. appium+python解决每次运行代码都提示安装Unlock以及AppiumSetting的问题

    appium+python解决每次运行代码都提示安装Unlock以及AppiumSetting的问题(部分安卓机型) 1.修改appium-android-driver\lib下的android-he ...

  6. Mybatis中Mapper的Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?

    还有很多其他的标签,<resultMap>.<parameterMap>.<sql>.<include>.<selectKey>,加上动态s ...

  7. 北京Uber优步司机奖励政策(3月18日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. LeetCode:33. Search in Rotated Sorted Array(Medium)

    1. 原题链接 https://leetcode.com/problems/search-in-rotated-sorted-array/description/ 2. 题目要求 给定一个按升序排列的 ...

  9. 如果看懂git -help

    每一个git 命令,都可以git * --help 打开git 的网页去看详细内容,也可以git * -help 在当前命令行里面看. 如下: zy@caoxinyu MINGW64 /f/git/i ...

  10. JS学习 用 arguments 对象模拟函数重载

    用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载: function doAdd() { if(arguments.length == 1) { alert(arguments[ ...