More Effective C++:Item 27
来源:互联网 发布:张北云计算产业园在哪 编辑:程序博客网 时间:2024/04/30 08:58
温习More Effective C++,对于Item 27:要求或禁止在堆中产生对象,整理思路于此文。
编译期控制
通过禁用定义对象所需的条件,即可在编译期阻止对象的定义。
- 定义堆对象所需的条件
- 定义非堆对象所需的条件
|||||
|独立非堆对象|不需要|public|public|
|成员非堆对象|不需要|public|public|
|基类非堆对象|不需要|public|public|
注意其中一点,作为成员堆对象,其可以是直接对象也可以是指针对象。而作为成员非堆对象,则只能是直接对象。
通过上表不难得出以下结论:
要求对象在堆中
禁用public构造或析构函数即可使得独立对象和成员对象无法定义在非堆位置,而相应提供伪构造或析构函数就不会影响其在堆中的定义。
然而对于基类对象却没有什么好的办法,因为无论是否在堆中,其定义条件都是相同的——public或protected的构造和析构函数。若声明构造或析构函数为private,基类对象的定义就会被完全禁止,也就是说该类将无法作为基类。
// 数字类。class Number{public: // 提供伪构造函数。 static Number* MakeInstance() { return new Number; } virtual ~Number() {}protected: // 将构造函数声明为protected。 Number() {} };//==============================================================================// 独立对象。//==============================================================================void DefineIndependentObject(){ //========================================================================== // 定义在堆中:正确。 //========================================================================== Number* heapObject = Number::MakeInstance(); delete heapObject; //========================================================================== // 定义在栈中:错误。 //========================================================================== Number nonheapObject;}//==============================================================================// 成员对象。//==============================================================================void DefineMemberObject(){ //========================================================================== // 定义在堆中:正确。 //========================================================================== { // 财产类包含一个数字类指针。 class Asset { public: Asset() : value( Number::MakeInstance() ) {} ~Asset() { delete value; } private: Number* value; }; Asset* heapObject = new Asset; delete heapObject; } //========================================================================== // 定义在栈中:错误。 //========================================================================== { // 财产类包含一个数字类。 class Asset { private: Number value; }; Asset nonheapObject; }}//==============================================================================// 子类对象//==============================================================================void DefineSubclassObject(){ // 负数类派生自数字类。 class NegativeNumber : public Number {}; //========================================================================== // 定义在堆中:正确。 //========================================================================== NegativeNumber* heapObject = new NegativeNumber; delete heapObject; //========================================================================== // 定义在栈中:正确。 //========================================================================== NegativeNumber nonheapObject;}
禁止对象在堆中
只需禁用public class new即可禁止独立对象定义在堆中,并且不会对其在非堆位置中的定义产生影响。
然而对于成员对象和基类对象却又不存在什么好的办法,因为只有定义了public构造和析构函数,它们才能被定义在非堆位置,然而这也会使得它们能被定义在堆中。同样的,若是将构造或析构函数定义为private,那么它们的定义将会被完全禁止。
#include <new>class Number{private: static void* operator new( std::size_t ) throw() { return nullptr; }};//==============================================================================// 独立对象。//==============================================================================void DefineIndependentObject(){ //========================================================================== // 定义在堆中:错误。 //========================================================================== Number* heapObject = new Number; delete heapObject; //========================================================================== // 定义在栈中:正确。 //========================================================================== Number nonheapObject;}
运行期控制
通过堆对象和非堆对象的不同创建流程来进行控制。其不同之处只有一点:创建堆对象时class operator new会被调用。然而,首先,这一点只对独立对象管用:基类堆对象和成员堆对象的class operator new不一定被调用。
#include <new>#include <iostream>class Number{public: static void* operator new( std::size_t ) throw() { std::cout << "class operator new for Number" << std::endl; }};class NegativeNumber : public Number{public: static void* operator new( std::size_t ) throw() { std::cout << "class operator new for NegativeNumber" << std::endl; }};class Asset { Number value; };int main(){ // 独立堆对象的class operator new被调用。 Number* independentObject = new Number; delete independentObject; // 看,基类堆对象的则没有被调用。 NegativeNumber* baseObject = new NegativeNumber; delete baseObject; // 看,子类堆对象的也没有被调用。 Asset* memberObject = new Asset; delete memberObject; return 0;}
然后,即使是对于独立对象,它也不怎么好用,具体请参考More Effective C++ Item27。
总结
控制对象的内存位置比较困难,能够完美实现的只有:
1. 要求独立对象和成员对象在堆中。
2. 禁止独立对象在对象。
- More Effective C++:Item 27
- More Effective C++:Item 27
- read Item 25 of《More Effective C++》
- 《more effective c++》Item M1:指针与引用的区别
- 《more effective c++》Item M5:谨慎定义类型转换函数
- 《More Effective C++》 Item M1:指针与引用的区别
- 《more effective c++》读书笔记
- More Effective C++(2)
- 《More Effective C++》读后感
- 《More Effective C++》笔记
- More Effective c++ Item M29:引用计数
- More Effective C++ Item M30:代理类
- More Effective C++ Item M34:如何在同一程序中混合使用C++和C
- 《more effective c++》Item M3:不要对数组使用多态
- 《More Effective C++》 Item M2:尽量使用C++风格的类型转换
- more effective c++——Item M30 代理类(一)多维数组的实现
- 《Effective C++》和《More Effective C++》汇总
- 《More Effective C++》读书笔记一
- iOS中nil 、NULL、 Nil 、NSNull的区别
- Linux内核分析(五)系统调用过程解析
- 大数相乘的两种算法比较
- 2015年阿里巴巴实习生招聘笔试题详细解析(研发大类:Java研发/C++研发)
- [Bash]检测外网IP,不一致时发送邮件。
- More Effective C++:Item 27
- 调用EXE 判断是否成功运行
- Git分支管理策略
- 查找
- javascript面向对象(继承)
- 使用JDBC连接Mysql数据库存入二进制图片并实现读取在PHP中打开展示。
- 反射机制总结----Field
- Unity3D避免代码被反编译
- nyoj 303 序号互换