看到了Effective c++的最后一章,最开始的那章---内存管理还没搞清楚,准备那章搞清楚完也写篇博客,不管怎样,有好的开始就应该让它有个完美的结束,杂项讨论这章是作者将那些分到哪章都不合适的就索性放到了最后讨论,我看完后从中摘出自己认为重要的坐下笔记,如果能帮得到大家,那就更荣幸了哈!
1.当我们定义一个类时,编译器会自动给我产生哪些成员函数?
解析:我们都知道,当我们定义类时,如果我们没有定义某些成员函数的话,编译器会总会给我们自动合成,这就是编译器默默为我们完成和调用函数,这些函数主要有以下几个
构造函数、析构函数、拷贝构造函数、赋值运算符、(non-const)取地址运算符和(const)取地址运算符这六个函数,其代码形式如下
如果我们定义一个空类,如下所示
//空类 class Empty{ };
//空类 class Empty{ //编译器会在我们用到这些函数时,如果类中没有定义,会调用自己生产的 Empty(); ~Empty(); Empty(const Empty &rhs); Empty& operator==(const Empty &rhs); Empty* operator&(); const Empty* operator&() const; };
下面是个NameObejct的模板类
template <typename T> class NameObject{ public: NameObject(const char *name , const T &value); NameObject(cosnt string &name , cosnt T &value); private: string nameValue; T objectValue; }; //当我们自己定义的类中有了编译器为我们生成的函数,那么它便不会给我们生产 //NameObject类有了构造函数,编译器不会再给我们生成 NameObject<int> no_1("Smallest Prime Number" , 2); //类中没有拷贝构造函数,所以调用编译器为我们产生的拷贝构造函数 NameObject<int> no_2(no_1);
上面大致讲述了,编译器为我们产生的拷贝构造函数是怎么工作的,下面就谈谈赋值运算符是怎么工作的,
我们稍微改下上面的模板类,来演示一下,赋值运算符不能工作的情境。
template <typename T> class NameObject{ public: NameObject(string name , const T &value); private: string &nameValue; const T objectValue; }; string newDog("xiaoa"); string oldDog("xiaob"); NameObject<int> p(newDog , 2); NameObject<int> s(oldDog , 29); p = s;
当执行赋值运算符时,p的数据成员的nameValue的引用应该绑定s.nameValue绑定的string对象,但是我们都知道定义引用时应该给予绑定的初始对象并且不能再更改,同时类中的另一个数据成员是const,不能被写入,所以编译器所产生的赋值运算符函数将会拒绝执行,如果想完成,必须自己定义赋值运算符函数。
对于上述这种情况,我们应该显示的拒绝不能执行的函数,在前面的条款中提到这点,当类中不可以执行编译器为我们默默生成的函数时,应该显式的拒绝它,怎么显式的拒绝呢?其实看了前面条款的同学都知道,只要将这个函数private即可,如下所示:
template <typename T> class NameObject{ public: NameObject(string &name , const T &value); private: NameObject& operator=(const NameObject &rhs); string &nameValue; const T objectValue; };
2.宁愿编译链接时出错,也不要再执行时出错!
答:自我感觉这点没什么好讲的,因为在编译链接时出错我们根据编译器提示的错误查找,一般情况下都可以搞定,然而,在执行期出错的原因就很多,很难断定,所以Effective c++就提出了,尽量让错误都在编译期显现出来,也就是改变类的设计方法,添加新的类型来检查,这仅仅是提供了思路,书上也给出了例子,但是感觉在实际的开发中很难去做,所以在此只是稍微提下记录,有兴趣的可以详细看书哈!
3.在使用非局部静态对象之前要先确定它已被初始化。
答:什么是非局部静态对象(non-local-static-object)呢?
定义于global 或者 namespace scope
在某个class 类中声明为static
在某个文件范围内定义为static
还是举个例子
class Test{ }; //非局部静态对象 Test test;
非局部静态对象的问题在于,如果这个非局部对象的初始化不依赖于其他对象的初始化,那么没什么问题,或者说如果是单一的编译单元的话也没什么问题,但是如果是不同的编译单元,这个编译单元中对象的初始化依赖另一个编译单元的初始化时那么此时就会产生问题,因为c++是支持分离的编译单元(不同编译单元的代码生成目标文件,然后链接起来形成可执行文件),因为c++的这种特性就会导致这种初始化动作时发生的问题。
如下例所示
class FileSystem{ }; FileSystem theFileSystem;//非局部静态对象 class Directory{ public: Directory(); }; Directory::Directory() { //该构造函数中依赖theFileSystem的初始化 } Directory tempDir;
class FileSystem{ }; FileSystem& theFileSystem() { static FileSystem tfs;//定义并且初始化静态对象 return tfs;//传回的引用指向tfs } class Directory{ public: Directory(); }; Directory::Directory() { //该构造函数中依赖theFileSystem的初始化 } Directory& tempDir { static Directory td; return td; };
Effective c++(笔记) 之 杂项讨论,布布扣,bubuko.com
原文地址:http://blog.csdn.net/computer_liuyun/article/details/29195151