-
拷贝构造函数和拷贝赋值运算符
1.1 当类内有指针成员时,必须自己定义拷贝构造函数和拷贝赋值运算符,进行深度复制,即自己重新申请一块空间进行拷贝,防止发生浅拷贝,只是拷贝地址,delete两次会造成内存管理错误,参见《C++ Primer Plus》第435页
1.2 当类内有引用成员或const成员时,必须自己定义拷贝构造函数和拷贝赋值函数,因为引用和const在指定后不允许重新赋值。== 具体使用const_cast去掉const属性还是先调用析构函数之后再赋值,还需要再去考证一下。==
const_cast -
为驳回编译器自动提供的机能,可将相应的成员函数声明为private并不予实现
例如单例模式:public class Singleton { private static Singleton* INSTANCE = new Singleton(); private Singleton(){} public static Singleton* getInstance(){ return INSTANCE; } }
-
当class不企图被当做是基类时,令其析构函数为虚函数是个馊主意,因为虚函数会产生虚函数指针,不仅占用内存,还可能因此不具有可移植性。
3.1 所有的STL容器都不带虚函数,所以不能继承STL容器
3.2 析构函数绝对不要抛出异常,比如对一个vector来说,在析构第一个元素期间有个异常被抛出,其余元素还是应该被销毁,否则会发生内存泄漏。但假设在调用期间,第二个元素在析构时又抛出异常,这时候两个异常同时存在的情况下,程序若不是结束执行就是导致不正确行为
3.3 如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕获任何异常,然后吞下异常或结束程序(abort) -
绝对不在构造和析构函数中调用虚函数,此时的虚函数执行的是基类那一层,没有下降到继承类
-
在operate = 时好的做法是考虑到异常
5.1 没有考虑分配内存不足或拷贝构造函数抛出异常class Widget { … private: Bitmap *pb; }
Widget& Widget::operate=(const Widget& rhs) { if(this==*rhs) return *this; delete pb; pb=new Bitmap(*rhs.pb); return *this; }
5.2 考虑异常的做法
Widget& Widget::operate=(const Widget& rhs) { Bitmap *pOrig=pb; //记住原先的pb pb=new Bitmap(*rhs.pb); delete pOrig; return *this; }
5.3 另一种使用copy and swap的做法
Widget& Widget::operate=(const Widget& rhs) { Widget temp(rhs); swap(temp); return *this; }
-
copying函数应该确保复制对象内的所有成员变量和所有基类成分
Effective C++笔记 —— 第二章
最新推荐文章于 2024-05-23 10:22:40 发布