zoukankan      html  css  js  c++  java
  • 读书笔记之Effective C++ 1.让自己习惯C++


    1.类的构造函数可以被声明为explicit,这可阻止它们被用来执行隐式类型转换(implicit type conversions),但是它们仍可被用来进行显式类型转换(explicit type conversions)

    class A{
    public:
       explicit A();
    }

    2.拷贝构造函数的调用:是在对象初始化的时候赋值。比如:A a1(B);或A a2 = B;
       赋值操作符:是在对象初始化完成后,从另一个同类型对象中拷贝其值到自我对象。比如:A a;a=B;

    3.类似C(C-like)中传值比传引用高效,面向对象C++中传引用比传值更高效。STL中传值更高效。

    4.取一个const地址合法,取enum地址不合法,取#define的地址通常也不合法。如果你不希望被人霍格一个pointer或reference指向你的某个整数常量,enum可以选择。

    5.对于单纯常量,最好以const对象或enum替换#define
       对于形似函数的宏,最好改用inline函数 + 模板 来替换#defines宏。

    6.void f1(const Widget* pw);和void f2(Widget const* pw);意义相同。


    char greeting[] = "Hello";
    char* p = greeting;
    const char* p = greeting; //p指向的值不能改变,指向的地址可变
    char* const p = greeting;  //p指针指向的地址不可变,指向的值可变
    const char* const p = greeting; //指向的地址和值都不能变。

    7.常量对象只能调用常量成员函数。

    8.关键字mutable定义的变量总是能够被更改,即使在const成员函数内。比如:定义mutalbe int a;

    9.将某些东西声明为const可帮助编译器侦测出错误用法。const可以被施加与任何作用域内的对象、函数参数、返回值类型、成员函数本体等等。

    10.当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免重复。

    比如:

    const char& operator[](int p) const{...}
    
    char& operator[](int p){
                  return const_cast<char&>(static_cast<const TextBlock&>(*this)[p]);
               }

    解释:cons_cast<char&> 是将返回值的const转换掉
          static_cast<const TextBlock&>(*this)[p]将*this加上const,使得可以调用const版本的operator[]。

    -------------------------------------------------------------------------------------------------------------------------------------
    11.C++ 规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。

    A::A(int a, char b, C &c)
    {
       _a = a;
       _b = b;
       _c = c;
    }

    在上面这个构造函数类,变量不是初始化,而是赋值,是基于赋值的初始化。初始化更早,发生于这些成员的default构造函数被自动调用之时,比进入构造函数体更早。
    但是,对于内置类型_a、_b不一定。


    A::A(int a, char b, C &c):_a(a),_b(b),_c(c){}

    而这个构造函数结构砼上上面的一样,但是效率较高。对于基于赋值的初始化,它首先给变量设初值,再给予赋指定的新值。
    而这个叫做成员初值列,采用copy的方式直接赋值,所以效率更高。

    还有,对于内置类型(int、char等等)赋值初始化和成员初始列的效率相同。

    对于有多个构造函数,且成员变量较多的情况,可以将内置类型放于构造函数体内。也可以将这些放在某个私有的函数中,可以供多个构造函数调用。
    这种做法在"成员变量的值是有文件或数据库读入"的时候特别有用。

    C++有着固定的成员初始化次序,基类总是在派生类之前初始化,class成员变量总是以其声明次序初始化。

    -------------------------------------------------------------------------------------------------------------------------------------

    12.编译单元:指产出单一目标文件的那些源码,基本上它是单一源码文件加上其所含入的头文件。


    local static:本地静态对象,也就是函数体中定义的static对象。
    non-local static:非本地静态对象,也就是非函数体中定义的对象,包括:全局global、namespace、class中的static对象。
    注:本地和非本地静态对象时相对函数而言。

    问题:C++对定义于不同编译单元内的non-local static对象的初始化次序无明确定义,也就是初始化顺序不确定。
          现在,至少两个源码文件,每个内至少含一个non-local static对象。现在如果某个编译单元内的某个non-local static对象的初始化使用了另一编译单元的non-local对象,而这个对象可能没有被初始化。


    解决:将用到的non-local static对象般到自己的专属函数内,并在此函数内声明为static。然后返回一个指向该对象的引用。

    FileSystem& getFileSystem(){
        static FileSystem fs;
        return fs;
    }
    
    -------------------------------------------------------------------------------------------------------------------------------

    C++保证函数体内的local static对象会在该函数被调用时,首次遇到该静态对象的定义式时初始化它。

    这样替换直接访问non-local static对象,保证了能够获得一个经历初始化的对象。更好的是,如果你从未调用这个对象,就会省去构造和析构的成本。

    至此,第一章我觉得需要记住的知识点就将完了。

    生命不止,奋斗不息!
  • 相关阅读:
    Atitit 人脸识别 眼睛形态 attilax总结
    Atitit 手机号码选号 规范 流程 attilax总结 v2 r99.docx
    atitit 板块分类 上市公司 龙头企业公司 列表 attilax总结.docx
    Atititi atiitt eam pam资产管理 购物表去年.xlsx
    使用cmd查看电脑连接过的wifi密码(一)
    常见十大web攻击手段 悟寰轩
    常见web攻击方式 悟寰轩
    【MYSQL数据库】MYSQL学习笔记mysql分区基本操作 悟寰轩
    Filter及FilterChain的使用详解 悟寰轩
    启动tomcat spring初始化两次问题(eg:@PostConstruct) 悟寰轩
  • 原文地址:https://www.cnblogs.com/huzongzhe/p/6735203.html
Copyright © 2011-2022 走看看