首页 > 代码库 > 高效C++ --经验条款(二)
高效C++ --经验条款(二)
STL迭代器以指针为根据塑造,所以迭代器的作用就像个T*指针,声明迭代器为const就像声明指针为const一样(既声明一个T* const指针),表示这个迭代器不得执行不同的东西,但它所指的东西的值是可以改动的。如果你希望迭代器所指的东西不可被改变(类似const T*指针),需要的是const_iterator。
Std::vector<int> vec;
Const std::vector<int>::iteratoriter = vec.begin(); //iter的作用像个T* const
*iter = 10; //没问题,可以改变iter所指物体
++iter; //错误
Std::vector<int>::const_iteratorciter = vec.begin(); //citer的作用就是个constT*
*citer =10; //错误 *citer是const
++citer; //可以改变citer;
两个成员函数如果只是常量性不同,可以被重载。
Mutavble可以释放掉non-static成员变量的bitwiseconstness约束。
对象的成员变量的初始化动作发生在进入构造函数本体之前。在成员列表内才算是成员的初始化动作。
当自己写类时,对于常规的类定义的方法,我们都会为类定义一个或多个构造函数、一个析构函数、一个copy assignment操作符。如果自己没有声明,编译器就会为他声明(编译器版本的)一个copy构造函数、一个copy assignment操作符号和一个析构函数。此外如果你没有声明任何构造函数,编译器也会为你声明一个default构造函数。所有这些函数都是public和inline的。同时只有当这些函数被需要时(被调用),他们才会被编译器创建出来。编译器版本生成的copy构造函数和copy assignment操作符,编译器创建的版本只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象。
但是有一点需要注意,如果你打算在一个“内含reference成员”的class内支持赋值操作,你必须自己顶一个copy assignment操作符。也就是说,如果一个类中的成员变量有引用类型,使用编译器自动生成的copy assignemnt操作符是不可靠的。如果类中有引用成员变量或者”内含const成员”,编译器不会为类生成copy assignment操作符。如果某个base classed将copy assignment操作符声明为pirvate,编译器将拒绝为其derived classes生成一个copy assignment操作符。
综上所述:编译器可以暗自为class创建default构造函数、copy 构造函数、copyassignment操作符,以及析构函数。但是在有些情况下编译器不会做这些事情的。比如类中如果有引用的成员变量或者const的成员变量,如果基类的copy assignment被声明为private类型。
所以如果不想使用编译器自动生成的函数,就该明确拒绝。如果将copy构造函数和copy assignment操作符都被声明为private而且没有定义,那么外部就不能使用拷贝构造函数和赋值构造函数了。这样就进制了对象的拷贝和赋值。
从此引申一点:
在BOOST库中有进制拷贝的类,只有子类继承了这个类,那么就会进制拷贝,为什么?嘉盛声明了一个类,
Classuncopyable{
Protected:
Uncopuable() {}
~uncopyable(){};
Private:
Uncopyable(const uncopyable&) ;
Uncopyable& operator=(constuncopyable&);
};
如果子类继承了这个类,即使在子类中不声明copy构造函数或者copyassignment操作符也不会被copy构造函数或copy assignment操作符,因为编译器不会为之生成。编译器就会直接决绝为之生成默认的这些函数。就是因为base class的拷贝函数是private.
为了不让编译器自动提供这些机能,可将相应的成员函数声明为private并且不给予实现,同时使用向uncopyable这样的base class也是一种方法。
到此为止,就明白编译器编译器可以为某些类(没有定义copy 构造函数、没有定义构造函数、没有定义copy assignment操作符)做什么了!编译器会为之生成一个的。同时也明白编译器在什么时候不会自动生成上面的几个函数,同时知道编译器生成的这些函数在被调用的时候都做了什么。同时知道了在不需要的时候怎么禁止编译器自动生成。
高效C++ --经验条款(二)