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对象,保证了能够获得一个经历初始化的对象。更好的是,如果你从未调用这个对象,就会省去构造和析构的成本。

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

    生命不止,奋斗不息!
  • 相关阅读:
    Python小工具:统计代码行数
    计算机图形学复习(一)
    牛客多校训练第一场 J.Different Integers
    数据校验码概述
    数据库复习第二章
    数据库复习第一章
    自动化AC器(带界面版)
    ZOJ 3747 Attack on Titans
    Codeforces Round #245 (Div. 1) B. Working out
    HDU 6266 Hakase and Nano 【博弈论】
  • 原文地址:https://www.cnblogs.com/huzongzhe/p/6735203.html
Copyright © 2011-2022 走看看