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

Effictive C++笔记

2016-03-07 20:08 197 查看

Effictive C++阅读笔记

const

Const, 可以在类外部修饰global或者namespace作用域中的常量,或者修饰文件、函数、或者区块作用域(block scope)中被声明为static的对象。也可以就修饰类内部的static以及non-static成员变量。面对指针,可以指出指针本身、指针所指物、或者两者都是const。

如果关键字const在号左边,表示被指物是常量(值不可被改动),如果出现在号右边,表示指针本身是常量(不得指向不同的东西,但是东西的值可以被改动);如果出现在*号两边,表示被指物和指针两者都是常量。

Const面对函数声明时的应用。

1.声明函数返回值为const,是为了 实现用户自定义类型和内置数据类型最大限度的保持一致性。给函数的返回值加上const标识,指定不能对函数的返回值进行赋值,如此一来,对于自定义类型,在进行a+b=c操作时,编译过程就会出错。

2.Const成员函数,是为了确认该成员函数能够作用于const对象身上。这类成员函数之所以重要,有两个理由,1)它们使得类接口比较容易被理解,知道哪个函数可以改动对象内容,哪个函数不行,这很重要。2),使得操作const对象称为可能。改善C++程序效率的一个根本方法就是以pass

by reference to const方式传递对象,这个技术可行的前提就是有const成员函数,可以用来处理获得的const对象。

函数加const和没加const,可以被重载的。这样在调用的时候对于const对象以及非const对象处理就可以出现不一样,因为实际执行的函数是不同的。处理const对象只能是const成员函数。

Const成员函数不可以更改对象内任何non-static成员变量。

mutable声明的变量,将永远处于可变的状态,即使在一个const函数中

如果函数的返回类型是内置类型,那么改动函数返回值从来就不合法。C++以by value返回对象这一事实,意味着改动的其实是一个副本,而不是值本身,这样并不是我们程序的初衷。

将non-const对象强制转为const对象,可以使用static_cast.移除这个动作只能使用const_cast完成。 Class的成员变量总是以其声明次序被初始化。

static

static对象,其寿命从被构造出来直到程序结束为止,因此stack对象,head_based对象都被排除。包括全局对象,定义在命名空间作用域内部的对象,在类中,在函数中,以及在文件作用域内被声明为static的对象。

函数内的static对象为局部static对象,其他对象称为为non-local static对象。程序结束时static对象会被自动销毁,也就是它们的析构函数会在main()结束时被自动调用。

实现一个单例模式

class single{
single(){

}
public static single(){
return nested.instance;
}
class nested{
static nested(){

}
static single instance = new single();
}
}


这样就按照需求,只有在需要访问single的实例时才会创建,而不会提前;

构造、析构、赋值运算

如果你创建了一个空类,那么经过C++处理后,就会给你添加类的默认构造函数,copy函数,析构函数,以及赋值操作。

c++不允许让“reference”改指向不同对象。这也就是为什么,如果你打算在一个内含引用类型的成员的类中支持赋值操作的话,就必须自己定义拷贝赋值操作符。上面说过,对于内含const成员的类也一样,不能支持赋值操作。

为了驳回编译器自动提供的功能(提供拷贝,赋值操作符,析构,默认构造函数),可以将相应的的成员函数声明为private并且不予实现。因为这些“编译器生成版”函数会尝试调用父类的对应函数,因为声明为private,所以是拒绝的。

析构函数的运作方式是:最深层派生的那个类其析构函数最先被调用,然后是器每一个父类的析构函数被调用。

带多态性质的父类(设计目的是作为父类接口处置子类对象)应该声明一个虚析构函数。如果类包含有任何virtual函数,那么他就应该拥有一个virtual的析构函数。

explicit关键字作用

只能用于类内部的构造函数声明上,作用于单个参数的构造函数。被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。

令赋值操作符返回一个reference to *this.

确保当对象自我赋值是operator=有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址,精心周到的语句顺序,以及copy-and-swap。

确定任何函数如果操作一个以上的对象,而其中多个对象时同一个对象时,其行为仍然正确。

当你编写一个copying函数,请确保(1)复制所有local成员变量,(2)调用所有父类的适当的copying函数。

资源

auto_ptr是个“类指针对象”,也就是所谓的智能指针,其析构函数自动对其所指对象调用delete。为了预防多个auto_ptr同时指向同一个对象, auto_ptr有个不寻常的性质,若通过拷贝构造函数或者拷贝赋值操作符复制他们,他们就会变成null,而复制所得的指针将取得资源的唯一拥有权。

reference-counting smart pointer。RCSP引用计数智慧指针,持续追踪共有多少对象指向某笔资源,并在无人指向它时自动删除该资源。tr1::shared_ptr就是其中一种,但是和auto_ptr一样,其析构函数内做delete而不是delete[],也就意味着动态分配而得的array身上使用auto_ptr和shared_ptr是不对的。

都提供一个get成员寒素,用来执行显示转换,也就是他会返回智能指针内部的原始指针(的复件)。

成对使用new和delete时要采用相同形式。

当时使用new时,有两件事情发生。第一,内存被分配出来。第二,针对此内存会有一个构造函数被调用。当使用delete时,也有两件事,针对此内存会有一个析构函数被调用,然后内存才被释放。delete的最大问题在于,即将被删除的内存之内究竟有多少个对象,这也就决定了有多少个析构函数必须被调用起来。

很简单,如果你调用new时使用【】,那么就必须在调用delete时也使用【】。如果没有,那么也不该在对应调用delete时使用【】。

以独立语句将newed对象存储于与智能指针内,如果不这么做,一旦异常被抛出,有可能导致难以察觉的资源泄露。

设计与声明

Boost的shared_ptr是原始指针的两倍大,以动态分配内存作为簿记用途和“删除器之专属数据”,以virtual形式调用删除器,并在多线程程序修改引用计数是蒙受线程同步化的额外开销。总之,他比原始指针大且慢,而且使用辅助动态内存。因为其支持定制删除器,可以防范跨DLL问题,可用来自动解除互斥锁。

尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并可避免切割问题。但是并不适用于内置类型,以及STL的迭代器和函数对象,因为对他们而言,pass-by-value更为恰当。

如果你需要为某个函数的所有参数(包括被*this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

实现

尽可能延后变量定义式的出现时间,因为要承受构造和析构成本。

C++提供的四种新式转型,

const_cast< T>(expression), 通常被用来将对象的常量性转除(cast away the constness).也是唯一有此能力的C++转型操作符。、

dynamic_cast< T>(expression),主要用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型,他是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。

reinterpret_cast意图执行低级转型,实际动作可能取决于编译器,也就表示它是不可移植。

static_cast用来强迫隐式转换,

继承与面向对象设计

有时候,基类构造函数的参数会有默认值,对于继承构造函数来讲,参数的默认值是不会被继承的。

如果定义一个空类,编译器会自动填补的是默认构造函数,拷贝构造函数,赋值构造函数,析构函数,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: