[Effective C++]构造/析构/赋值运算

条款05:了解C++默默编写了并调用了那些函数

请记住:

  • 编译器可以暗自为class 创建default构造函数,copy构造函数,copy assignment 操作符,以及析构函数
class Empty
{
public:
    Empty(){...}                              //default constructor
    Empty(const Empty& rhs){...}              //copy constructor
    ~Empty(){...}                             //destructor
    Empty& operator=(const Empty& rhs){...}   //copy assignment operator
};

条款06:如果不想使用编译器自动生成的函数就应该明确的拒绝

请记住:

  • 为驳回编译自动(暗自)提供的机能,可将相应成员函数声明为private并且不予以实现.使用像Uncopyable这样的base class 也是一种做法。

一旦你定义了自己的构造函数,不论函数参数如何,编译器都不再自动帮你产生构造函数。
如果你想阻止copying,则要声明一个private的copy构造函数和copy assignment操作符,并且不去定义它们。这样,一旦有人尝试进行copy构造或赋值,编译器就会报错。

条款07:为多态的基类,声明virtual析构函数

请记住:

  • polymorphic(带多态性质的)base class 应该声明一个virtual析构函数如果class带有任何virtual 函数,他就该拥有一个virtual析构函数。
  • Classes 的设计目的如果不是作为base class 适用,或者不是为了具备多态性质就不该声明为virual析构函数。

任何class只要带有virtual函数都几乎确定应该也有一个virtual析构函数。
如果class不含virtual函数,通常表示它并不意图被用做一个base class。当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。

欲实现virtual函数,对象必须携带某些信息,主要用来在运行期决定哪一个virtual函数被调用。这份信息通常是由一个所谓vptr(virtual table pointer)指针指出。vptr指向一个由函数指针构成的数组,称为vtbl(virtual table):每一个带有virtual函数的class都有一个相应的vtbl。当对象调用某一virtual函数,实际被调用的函数取决于该对象的vptr所指的那个vtbl——编译器在其中寻找适当的函数指针。

如果class内含irtual函数,其对象的体积会增加(由于ptr)。另外,C++的对象也不会和其他语言(如C)内的相同声明有着一样的结构(因为其他语言的对应物没有ptr),因此也不能把它传递至(或接受自)其他语言所写的函数,即不再具有移植性。

条款08:别让异常逃离析构函数

请记住:

  • 析构函数绝对不要吐出异常如果一个被析构函数调用的函数可能抛出异常析构函数应该捕获任何异常,然后吐下他或者结束程序。
  • 如果可会需要对某个操作函数运行期间抛出异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。

对于C++,有两个异常同时存在的情况下,程序若不是结束执行,就是导致不明确行为。因此假如某对象的析构函数可能抛出异常,当我们试图释放一个包含装有该类对象的容器时,假设在析构第一个元素期间,有个异常被抛出,容器中的其他元素还是要被销毁,因此将调用它们各个析构函数,如果在这期间又有另一元素在析构过程中抛出了异常,故事将如何发展便不得而知了。

条款09:绝不在构造和析构过程中调用virtual函数

请记住:

  • 在构造函数和析构函数期间不能调用virtual函数因为这类调用从不下降至derived class。

由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行时derived class的成员变量尚未初始化。如果此期间调用irtual函数下降至derived class阶层,要知道derived class的函数几乎必然取用local成员变量,而那些成员变量尚未初始化。

条款10:令operator=返回一个reference to *this

请记住:

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

条款11:在operator=中处理“自我赋值”

请记住:

  • 确保对象自我赋值时operator=有良好的行为,其中技术包括比较“来源对象”和“目的对象”的地址、精心周到的语句顺序,以及 copy-and-swap。
  • 确定任何对象操作一个以上的对象,而其中多个对象时同一个对象时,其行为仍然正确。

条款12:赋值对象时勿忘赋值对象的每一个成分

请记住:

  • copying 函数应该确保赋值“对象的所有成员变量”有有base class 成分。
  • 不要尝试以某个copying函数实现另一个copying函数,应该将共同的机能放进第三个函数中并由两个函数共同调用。

当你编写一个copying函数,请确保(1)复制所有local成员变量,(2)调用所有base class内的适当的copying构造函数,(3)不要尝试以某个copying函数实现另外一个copying函数。

时间: 2024-08-03 11:23:33

[Effective C++]构造/析构/赋值运算的相关文章

Effective C++ -- 构造析构赋值运算

05.了解C++默默编写并调用哪些函数 编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual 成员变量中有引用和const成员时,无法自动生成copy assignment函数 基类将copy assignment操作符声明为private时,编译器拒绝为其derived classes生成一个copy assignment操作符. 06.若不想使用编译器自动生成的函数,就该明确拒绝 将自动生成的默认构造函数,拷贝构造函数,copy assignment声明为pr

Effective C++ —— 构造/析构/赋值运算(二)

条款05 : 了解C++默默编写并调用哪些函数 水电费 条款02 : 尽量以const,enum,inline 替换#define 水电费 条款02 : 尽量以const,enum,inline 替换#define 水电费 条款02 : 尽量以const,enum,inline 替换#define 水电费

Effective C++笔记:构造/析构/赋值运算

条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函数时,编译器会给我们构造默认的. 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类也不无生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 将拷贝构

《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记

章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(2)-读书笔记 <Effective C++>第8章 定制new和delete-读书笔记 条款09:绝不在构造和析构过程中调用virtual函数 你不该在构造和析构函数期间调用virtual函数,因为这样的调用不会带来你预期的结果. (1)在der

《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记

章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effective C++>第8章 定制new和delete-读书笔记 条款05:了解C++默默编写并调用哪些函数 当C++处理过一个空类后,编译器就会为其声明(编译器版本的):一个拷贝构造函数.一个拷贝赋值运算符和一个析构函数.如果你没有声明任何构造函数,编译器还会声明一个默认构造函数.所有这些函数都被声明为pub

Effective C++ 笔记二 构造/析构/赋值运算

条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inline. 1 class Empty { 2 public: 3 Empty() {...} 4 Empty(const Empty& rhs) {...} 5 ~Empty() {...} 6 Empty& operator=(const Empty& rhs) {...} 7 }; 如

【Effective C++】构造/析构/赋值运算

条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函数时,编译器会给我们构造默认的. 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类也不无生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 将拷贝构

Effective C++ 02构造/析构/赋值运算(待续)

条款05:了解C++默默编写并调用哪些函数 如果你自己没声明,编译器就会为类声明(编译器版本的)一个拷贝构造函数,一个拷贝赋值操作符和一个析构函数. 此外如果你没有声明任何构造函数,编译器也会成为你声明一个默认构造函数.所有这些函数都是public且inline. 惟有当这些函数被需要(被调用),它们才会被编译器创建出来.即有需求,编译器才会创建它们. 请记住: 编译器可以暗自为类创建默认构造函数.拷贝构造函数.拷贝赋值操作符,以及析构函数. 条款06:若不想使用编译器自动生成的函数,就该明确拒

Effective C++笔记(二):构造/析构/赋值运算

参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数(再次感觉原文翻译的实在是太啰嗦了!). 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类 也不能生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生