您的位置:首页 > 编程语言 > C语言/C++

读书笔记之Effective C++ 1.让自己习惯C++

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

至此,第一章我觉得需要记住的知识点就将完了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: