More Effective C++:Item 27
来源:互联网 发布:刷机备份游戏数据 编辑:程序博客网 时间:2024/04/30 12:39
温习More Effective C++,对于Item 27:要求或禁止在堆中产生对象,整理思路于此文。
编译期控制
通过禁用定义对象所需的条件,以在编译期阻止对象的定义。
下表列出了不同位置上不同形式的对象定义所需函数的最低访问权限。
注意:
- 通过提供伪构造函数可以让指针对象摆脱对class operator new和构造函数的依赖。
- 不存在非堆对象的指针成员形式。
- 基类对象的class operator new不是必需的,因为派生类可以重载该函数。
- 成员对象的class operator new不是必需的,因为整体类不需要调用它。
结论:
- 独立形式: 通过声明class operator new为private可以禁止对象定义在堆上,如果声明构造函数为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. 禁止独立对象在对象。
0 0
- 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程序支持64位以及project.pbxproj文件的介绍
- 利用jabx进行xml与javabean的数据绑定
- POJ3278.Catch That Cow
- Android性能优化典范
- 13. ibatis最佳实践
- More Effective C++:Item 27
- django下ajax请求403(FORBIDDEN)的解决办法
- 《learn objective-c on the Mac for OS X and IOS》<译名>《objective-C基础教程》
- 设计模式--组合模式
- 部分华为校园招聘机试试题及答案(C语言版本)
- NSDatepicker
- MySQL连接查询
- HDU 2473 Junk-Mail Filter(删点)
- 【Obective-C编程开发】Objective-C之BOOL一清二楚