学习程序语言根本大法是一回事,学习如何以某种语言设计并实现高效程序则是另一回事。

一组明智选择并精心设计的classes、functions、templates可使程序编写容易、直观、高效、并且远离错误。

带着问题去品读这本经验著作:

设计上的讨论:
“如何在两个不同的做法中择一完成某项任务?”

  • 选择继承(inheritance) or 模板(templates)?
  • 选择public继承还是private继承?
  • private继承还是composition(复合)?
  • 选择number函数还是non-number函数?
  • 选择pass-by-value还是pass-by-reference?

即使完全知道该做什么,完全进入正轨可能还是可能有点棘手。

  • 什么是assignment操作符的适当返回类型(return type)?
  • 何时该令析构函数为virtual?
  • 当operator new无法找到合适的内存空间时该如何行事?

榨出这些细节很重要,本书将带你趋凶避吉,避免那些未可预期、神秘难解的程序行为。

软件设计和实现是复杂的差事,被硬件、操作系统、应用程序的约束条件涂上五颜六色,所以我能做的最好的就是提供指南,让你得以创造出更棒的程序。

准则天生就带有例外。这就是为什么每个条款都有解释与说明。这些解释与说明是本书最重要的一部分。唯有了解条款背后的基本原理,你才能够决定是否将它套用于你所开发的软件,并奉行其所昭示的独特约束。

本书的最佳用途:

本书的最佳用途就是彻底了解 C++ 如何行为为什么那样行为以及如何运用其行为形成优势

下面是每个C++程序员都应该了解的一份小小的 C++ 词汇。

  1. 声明式

    所谓声明式(declaration)是告诉编译器某个东西的名称和类型,但是略去细节。

        extern int x;       //对象声明式
    std::size_t numDigits(int number); //函数声明式
    class Widget; //类声明式 template<typename T> //模板声明式
    class GraphNode;
  2. 签名式

    每个函数的声明揭示其签名式(signature),也就是参数和返回值类型。一个函数的签名就等同于该函数的类型。numDigits函数的签名是std::size_t (int),也就是说“这个函数获得一个int 并返回一个 std::size_t”。

  3. 定义式(definition)

    定义式的任务是提供编译器一些声明式所遗漏的细节。对对象而言,定义式是编译器为此对象拨发内存的地点
    对function 或者 function template 而言,定义式提供了代码本体。对 class 或者 class template 而言,定义式列出它的成员:

        int x;                     //对象定义式
    std::size_t numDigits(int number) //函数定义式
    {
    //返回其参数的数字个数
    std::size_t digitsSoFar = 1;
    while ((number /= 10) != 0)
    ++ digitsSoFar;
    return digitsSoFar;
    } class Widget //class 定义式
    {
    public:
    Widget();
    ~Widget();
    ...
    }; template<typename T> //template 的定义式
    class GraphNode{
    public:
    GraphNode();
    ~GraphNode();
    ...
    };
  4. 初始化(initialization)

    初始化(initialization)是“给予对象初值”的过程。对用户自定义类型的对象而言,初始化由构造函数执行。
    所谓default构造函数是一个可被调用而不带任何实参者。这样的构造函数
    要不没有参数要不就是每个参数都有缺省值

    class A{
    public:
    A(); //default构造函数
    }; class B{
    public:
    explicit B(int x = 0, bool b = true); //default构造函数
    } class C{
    public:
    explicit C(int x); //不是default构造函数
    }

    上述的class B 和 C的构造函数都被声明为 explicit,这可阻止它们被用来执行隐式类型转换(implicit type conversions),但他们仍可被用来进行显示类型转换(explicit type conversions):

    void doSomething(B bobject);     //此函数接受一个类型为B的对象
    
    B bObj1;                         //一个类型为B的对象
    doSomething(bObj1); //没问题,传递一个B给
    //doSomething函数 B bObj2(28); //没问题,根据int 28 建立一个B
    //(函数的bool参数缺省为true)
    doSomething(28); //错误!doSomething 应该接受
    //一个B,不是一个 int ,
    //int 和 B 之间没有隐式转换
    doSomething(B(28)); //没问题,使用 B 构造函数将 int
    //显式转换为一个 B 以促成此调用

    被声明成 explicit 的构造函数禁止编译器执行非预期的类型转换。除非你有一个好理由允许构造函数被用于隐式类型转换,否则你应该把他声明为 explicit 。

  5. copy构造函数 和 copy assignment操作符

    copy构造函数被用来”以同类型对象初始化自我对象”
    copy assignment 操作符被用来“从另一个同类型对象中拷贝其值到自我对象”:

    class Widget{
    public:
    Widget(); //default构造函数
    Widget(const Widget& rhs); //copy构造函数
    Widget& operator=(const Widget& rhs); //copy assignment操作符
    ...
    };
    Widget w1; //调用default构造函数
    Widget w2(w1); //调用copy构造函数
    w1 = w2; //调用 copy assignment操作符

    当你看到赋值符号时请小心,因为“=”语法也可用来调用copy构造函数:

    Widget w3 = w2;              //调用copy构造函数

    如何区别是”copy构造”还是”copy赋值”:
    如果一个新对象被定义,一定会有一个构造函数被调用,不可能调用赋值操作。如果没有新对象被定义(例如前面的 “w1 = w2”语句),就不会有构造函数被调用,那么当然就是赋值操作被调用。

    copy构造函数是一个尤其重要的函数,因为他定义了一个对象如何 pass-by-value(以值传递)。
    举个例子:

    bool hasAcceptableQuality(Widget w);
    ...
    Widget aWidget;
    if (hasAcceptableQuality(aWidget)) ...

    参数w是以 by value 方式传递给 hasAcceptableQuality,所以在上述调用中 aWidget被复制到 w 体内。这个复制动作由 Widget 的copy构造函数完成。pass-by-value 意味“调用 copy 构造函数”。以 by value 传递用户自定义类型通常是个坏主意, Pass-by-Reference-to-const往往是比较好的选择。

  6. 未定义行为(Undefined behavior)[不明确行为]

    int* p = 0;               //p是一个null指针
    std::cout << *p; //对一个null指针取值会导致不明确的行为
    //null指针可读不可写 char name[] = "Darla"; //name 是个数组,大小为6(别忘记最尾端的null)
    char c = name[10]; //只涉及一个无效的数组索引

【Effective C++ 读书笔记】导读 Introduction的更多相关文章

  1. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  2. Effective STL读书笔记

    Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...

  3. effective c++读书笔记(一)

    很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...

  4. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  5. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  6. Effective Objective-C 读书笔记

    一本不错的书,给出了52条建议来优化程序的性能,对初学者有不错的指导作用,但是对高级阶段的程序员可能帮助不是很大.这里贴出部分笔记: 第2条: 使用#improt导入头文件会把头文件的内容全部暴露到目 ...

  7. 【Effective C++读书笔记】序

    C++ 是一个难学易用的语言! [C++为什么难学?] C++的难学,不仅在其广博的语法,以及语法背后的语义,以及语义背后的深层思维,以及深层思维背后的对象模型: C++的难学还在于它提供了四种不同而 ...

  8. Effective Java 读书笔记(一):使用静态工厂方法代替构造器

    这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...

  9. Effective C++读书笔记(转)

    第一部分 让自己习惯C++ 条款01:视C++为一个语言联邦 一.要点 ■ c++高效编程守则视状况而变化,取决于你使用c++的哪一部分. 二.扩展 将c++视为一个由相关语言组成的联邦而非单一语言会 ...

随机推荐

  1. (初学)wpf仿QQ界面-整体布局

    跟一个小学弟一起学习wpf,小学弟是刚初中毕业,对编程刚刚接触,我挺怕自己带的不好,影响小学弟以后在编程方向的学习兴趣.我承认自己水平不高,但是在努力去学习新知识!一起加油吧!在此以博客,记录学习进度 ...

  2. dll托管于非托管

    托管的DLL组件可以在VS 直接添加引用,在使用using dll的文件命名空间就可以使用 非托管的DLL组件,只能通过using system.Runtime.InteropServices:引入 ...

  3. Sass基础(二)

    五.嵌套 在Sass中,嵌套有三种方式:选择器嵌套.属性嵌套.伪类嵌套 1.选择器嵌套 2.属性嵌套 3.伪类嵌套 六.混合宏 当样式变得越来越复杂,需要重复使用大段的样式时,使用变量就无法达到目的了 ...

  4. 【起航计划 008】2015 起航计划 Android APIDemo的魔鬼步伐 07 App->Activity->Persistent State 保存状态 SharedPreferences onPause onResume

    Android 提供了多种存储数据的方法,其中最简单的是使用Shared Preferences. Shared Preferences 可以存储 Key/value 对,Shared Prefere ...

  5. Android开发基础

    一.Android开发环境搭建 1.下载安卓SDK 官方下载地址:http://developer.android.com/sdk/index.html 2.下载安装JDK 官方下载地址:JDK6 h ...

  6. C#变量、常量

    变量 一.命名变量:标识符 为变量命名时要遵循C#语言的命名规范: 1.变量名只能由字母.数字和下划线组成,而不能包含空格.标点符号.运算符等其他符号 2.变量名不能与C#中的关键字名称相同   二. ...

  7. [原创]Debian9 从零编译配置Redis4.0

    序言 Redis 一.准备工作 1.1 更新系统安装包列表 没啥,就他喵想用个最新的. # apt update 1.2 创建需要使用的目录 创建目录source和web,分别用来放源码和编译后的文件 ...

  8. Struts2_HelloWorld_7_2

    第一个程序的流程图: Struts2.x 的作用:把请求和展现分开.

  9. 炫酷的Html+css (一)

    博客园在别的 博主看到一个样式, 里面有一段这样的 正方体旋转的 动态图 吸引了我. 找博主要了代码, 贴出来 与大家共享. 鼠标放上去会展开 一大一小两个正方体, 鼠标悬浮上去, 外面的正方体会展开 ...

  10. C#队列Queue,利用队列处理订单

    一.什么是队列 队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. 这是摘抄网上的.做了 ...