随笔分类 -  Effective/More Effective C++ 读书笔记

摘要:1. 有些智能指针类(比如shared_ptr)不支持隐式类型转换,假设存在这样两个函数:void fun(shared_ptr lhs,int rhs);int foo();View Code那么对于以下函数调用:fun(new int,foo());将不能通过编译,解决方法之一:fun(shar... 阅读全文
posted @ 2015-08-23 15:28 Reasno 阅读(219) 评论(0) 推荐(0)
摘要:(参考自 http://www.cnblogs.com/hazir/p/new_and_delete.html)1. new和delete不是函数,是C++的关键字.2. new一个对象的实际操作分为两步:1). 调用标准库函数operator new分配内存 2)调用构造函数初始化(如果new的是... 阅读全文
posted @ 2015-08-23 11:27 Reasno 阅读(193) 评论(0) 推荐(0)
摘要:1. 有时资源管理类(resource-managing classes)需要提供对资源的直接访问,这就需要将RAII class对象转换为其内含的原始资源,有两种做法可以达成目标:显式转换和隐式转换.2. 显式转换:shared_ptr和auto_ptr都提供一个get成员函数,用来执行显式转换,... 阅读全文
posted @ 2015-08-23 09:53 Reasno 阅读(212) 评论(0) 推荐(0)
摘要:1. 条款13导入RAII的观念:资源获取时机便是初始化时机,资源会在不需要的时刻被销毁,典型代表就是shared_ptr和weak_ptr,但是并非所有资源都是堆内存,例如外存和堆栈,在这种情况下,auto_ptr,shared_ptr,weak_ptr显然不适合作为资源管理类,这就需要建立自己的... 阅读全文
posted @ 2015-08-22 21:42 Reasno 阅读(239) 评论(0) 推荐(0)
摘要:1. 在使用堆内存时,需要手动delete指针以防内存泄露,但是有些例外情况(例如发生异常)会使得内存资源无法释放,此外,使用者也极有可能忘记释放堆内存,因此需要"以对象管理资源",也就是把资源放进对象内,用析构函数来确保资源被释放,这种思想被称为"资源取得时机就是初始化时机"(Resource A... 阅读全文
posted @ 2015-08-22 20:51 Reasno 阅读(490) 评论(0) 推荐(0)
摘要:1. 编译器合成的拷贝构造函数默认调用基类的拷贝构造函数,合成的拷贝构造操作符也是一样.2. 对于自己编写的拷贝构造函数,编译器不再默认调用基类的拷贝构造函数,仅在拷贝构造函数中没有初始化基类部分时调用默认构造函数.对于自己编写的拷贝赋值操作符,编译器不额外作任何操作(即使类的编写者忘记调用基类的拷... 阅读全文
posted @ 2015-08-22 16:46 Reasno 阅读(158) 评论(0) 推荐(0)
摘要:1. 为了支持形如“a=b=c”的连锁形式,最好令operator=返回一个reference to *this.2. 如果类中含有用于指向堆内存的指针,那么赋值操作符就要注意自我赋值的问题,例如:class A{public: ... A& operator=(const A& tmp... 阅读全文
posted @ 2015-08-22 15:08 Reasno 阅读(280) 评论(0) 推荐(0)
摘要:1. 在一个继承体系中,最底层的派生类在构造过程中,先初始化基类部分,再按继承层次依次初始化派生类部分,因此被构造的对象先作为一个基类对象,再按继承层次依次成为派生类对象,例如,在继承层次A→B→C→D中,构造一个D类对象,其依次经历了A→B→C→D的转变,因此对于以下代码:#include usi... 阅读全文
posted @ 2015-08-22 15:04 Reasno 阅读(240) 评论(0) 推荐(0)
摘要:1. 当异常发生时,如果异常发生在一个try块内部,程序就会跳出该try块,并逐层寻找匹配的catch,跳出try块的过程中,会销毁该try内创建的对象并调用析构函数,如果调用析构函数的过程中又发生异常,程序就会调用标准库terminate函数(terminate函数调用abort函数)结束执行,例... 阅读全文
posted @ 2015-08-22 11:09 Reasno 阅读(601) 评论(0) 推荐(0)
摘要:1. 成员函数只有被需要(被调用)才必须有定义,同理,只有当默认构造函数,拷贝构造函数,赋值操作符,析构函数被需要而类定义它们时,它们才会被编译器创建出来(除非函数在基类中被声明为虚函数,编译器产生的函数是非虚的,public的).2. 并不是只要类没有定义默认构造函数,拷贝构造函数,赋值操作符时编... 阅读全文
posted @ 2015-08-19 15:20 Reasno 阅读(195) 评论(0) 推荐(0)
摘要:1. 如果一个类将要作为基类,那么它应该具有一个虚析构函数以防止delete经由基类指针指向的派生类对象时发生的"局部销毁"问题,避免造成内存泄露,数据结构败坏,在调试器上浪费时间等问题;任何带有虚函数的类几乎肯定需要一个虚析构函数.2. 在不必需的情况下不应该将成员函数设为虚函数,否则,如果导致一... 阅读全文
posted @ 2015-08-18 17:34 Reasno 阅读(208) 评论(0) 推荐(0)
摘要:1. 某些类的含义决定了它们不具备某些功能,也就是说某些函数不能被创造出来以防被错误的使用(例如定义一个Book类,它含有一个表示ISBN的变量,这种情况下拷贝构造函数以及赋值操作符显然是没有意义的,因为任何两种书的ISBN都不同),但是编译器在类的创建者没有声明默认构造函数,拷贝构造函数,赋值操作... 阅读全文
posted @ 2015-08-18 17:10 Reasno 阅读(234) 评论(0) 推荐(0)
摘要:1. 对于内置类型,如果变量在全局作用域内定义,默认初始化为0,如果变量在局部作用域内定义,默认不进行初始化;对于类类型,默认调用默认构造函数进行初始化,如果没有默认构造函数,则必须显式初始化.2. 构造函数对成员进行初始化的动作发生在初始化列表中而不是函数体内,在函数体内进行的"初始化"实际上是赋... 阅读全文
posted @ 2015-08-18 12:48 Reasno 阅读(354) 评论(0) 推荐(0)
摘要:1. const可被施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体.用const修饰指针,如果const出现在*之前,表明指针不能更改所指向的对象的内容,如果const出现在*之后,表明指针只能指向同一块内存.另外int const*p和const int*p含义相同.如果对象成员有... 阅读全文
posted @ 2015-08-17 23:37 Reasno 阅读(475) 评论(0) 推荐(1)
摘要:1. 有些情况下,宁可以编译器替换预处理器,因为#define并不被视为语言的一部分从而导致某些问题.2. 不带参数的宏展开引起的符号"丢失"问题. 例如,对于"#define ASPECT_RATIO 1.635",编译器在处理源代码之前ASPECT_RATIO就已经被替换为1.635,于是记号名... 阅读全文
posted @ 2015-08-17 20:49 Reasno 阅读(327) 评论(0) 推荐(0)
摘要:1.一开始,C++只是C加上一些面向对象特性,最初名称为"C with Classes"(带类的C).2.如今的C++已经是个多重泛型编程语言,同时支持过程形式(procedural),面向对象形式(object-oriented),函数形式(functional),泛型形式(generic),元编... 阅读全文
posted @ 2015-08-17 19:32 Reasno 阅读(313) 评论(0) 推荐(0)
摘要:1. 由条款12知,如果catch子句捕获异常采用按值传递,那么被抛出的异常要被复制两次,这降低了效率,而且将派生类对象传给基类对象有可能会产生切割问题,但是按值传递也有它的好处,在catch子句重新throw异常的时候,它可以选择throw经catch子句处理过的异常还是原来的异常,这增加了灵活性 阅读全文
posted @ 2015-06-26 22:38 Reasno 阅读(231) 评论(0) 推荐(0)
摘要:1. 函数return值与try块throw exception、函数接收参数与catch字句捕获异常相当类似(不仅声明形式相像,函数参数与exception传递方式都有三种:by value,by reference ,by pointer(本质上也是by value) )。 2. 尽管函数调用与 阅读全文
posted @ 2015-06-26 21:57 Reasno 阅读(419) 评论(0) 推荐(0)
摘要:1. ”两种情况下destructor会被调用。第一种情况是当对象在正常情况下被销毁,也就是当它离开了它的生存空间或是被明确的删除;第二种情况是当对象被exception处理机制——也就是exception传播过程中的stack-unwinding(栈展开)机制——销毁。” 2. 当destruct 阅读全文
posted @ 2015-06-26 20:45 Reasno 阅读(277) 评论(0) 推荐(0)
摘要:1. “C++ 只会析构已完成的对象”,“面对未完成的对象,C++ 拒绝调用其析构函数”,因为对于一个尚未构造完成的对象,构造函数不知道对象已经被构造到何种程度,也就无法析构。当然,并非不能采取某种机制使对象的数据成员附带某种指示,“指示constructor进行到何种程度,那么destructor 阅读全文
posted @ 2015-06-26 19:54 Reasno 阅读(413) 评论(0) 推荐(0)