Effective C++ 10
10.假设写了operator new,就要同一时候写operator delete。
为什么要写自己的operator new和delete,首先这不叫重载,这叫隐藏。 new仅仅是用来申请空间,而构造函数是在申请的空间的基础上继续初始化。
为了效率。缺省的operator new 进行内存分配是并不只分配一块所需大小的内存,由于delete释放内存时要知道指针所指向内容的大小,所以,new时会有一个块来储存内存块的大小,而delete时,会依据这个大小来推断删除内存大小。所以当一个类本身非常小的时候,这样做,既浪费时间于内存大小的推断,也浪费空间于内存大小的保存。对于某些类较小,且须要一定数量的这些小对象来储存数据时,最好能写一个operator new 来节约空间与时间。
而因为自己的Operator new申请的内存块中没有保存内存块的大小,导致使用缺省的delete时,会导致不可预測的后果。所以若写了operator new ,就必须同一时候写operator delete。
一般解决方法是 申请一大块内存,作为内存池,将其分为若干块,每块大小正好为储存对象的大小。当前没有被使用时。
尝试将这样的固定大小内存的分配器封装起来。
//内存池的实现。
class Pool{
public:
Pool (size_t n,int size);
void* alloc(size_t n);//为一个对象分配足够的内存
void free(void* p,size_t n);//将p指定的内存返回到内存池。
~Pool();//释放内存池中的所有资源
private:
void* block;
const int BLOCK_SIZE;//池内存放块的数量
void* list;
}; Pool::Pool(size_t n,int size):BLOCK_SIZE(size){
block = ::operator new(n*size);
int i;
for(i = 0;i<BLOCK_SIZE -1;i++){
*(unsigned int*)((unsigned int)block + n*i) =
(unsigned int)block + n*(1+i);
}
*(unsigned int*)((unsigned int)block + n*i) = 0;
list = block;
} void* Pool::alloc(size_t n){
void* p = list;
if(p){//假设自由链表中还有元素,即还有空间
list = (void*)*(unsigned int *)list;
return p;
}else{
throw std::bad_alloc();
}
return p;
} void Pool::free(void* p,size_t n){
if(0 == p)return;
*(unsigned int*)((unsigned int)p) = (unsigned int)list;
list = (void*)p;
}
Pool::~Pool(){
delete block;
} class A{
public:
int a;
static void* operator new (size_t size);
static void operator delete (void* p,size_t size);
A(int x){a = x;}
private:
static Pool memPool; };
Pool A::memPool(sizeof(A),10);
inline void* A::operator new(size_t size){
return memPool.alloc(size);
}
inline void A::operator delete(void* p,size_t size){
memPool.free(p,size);
}
int main(){
A* list[10];
for(int i = 0 ; i < 10;i++){
list[i] = new A(i);
}
int i = 0;
for(int i = 0 ; i < 10;i++){
delete list[i];
}
i = 1;
for(int i = 10 ; i < 20;i++){
list[i-10] = new A(i);
}
for(int i = 0 ; i < 10;i++){
delete list[i];
} system("pause"); }
这是一个内存池的实现,结果感觉尽管实现了内存池的基本功能,但写的不好看。。。譬如一些问题没有解决,假设要求内存大于池的最大容量的处理,以及释放池内元素时,假设反复释放须要进行一些推断此块内存释放已释放。
忽略上面代码,简单分析一下内存池的基本功能:alloc 为对象申请空间的请求提供内存,而free释放对象如今所在的内存。
这里说的写了 operator new 就要写相应的operator delete,由于你在自己写的new中一定会定义一些其它的操作,使的数据的组织结构不是一个简单的new就实现的,可能有多块动态地址,或者可能像内存池中并没有实际的去申请新的空间,所以一定要依据自己写的new中的操作,设计相应的delete操作。
Effective C++ 10的更多相关文章
- Effective C++(10) 重载赋值操作符时,返回该对象的引用(retrun *this)
问题聚焦: 这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量. 细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧. 还是以一个例子开始: Demo // 连锁赋值 x ...
- Effective Java 10 Always override toString() method
Advantage Provide meaningful of an object info to client. Disadvantage Constrain the ability of chan ...
- Effective C++ .10,11 operator=的约定与注意
1. 返回一个reference to *this 返回一个指向自身的引用符合惯例,可以进行如(a=c).modify()类似的操作,即可以形成链式操作,否则修改的只是一个临时对象.这个和Java中常 ...
- Effective Java Index
Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...
- C++异常处理:try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- C++异常处理: try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- 卓越管理的秘密(Behind Closed Doors)
或许提到本书甚至本书的作者Johanna Rothman我们会感到些许陌生,那么提起她的另一本获得素有软件界奥斯卡之称的Jolt生产效率大奖的名著<项目管理修炼之道>,会不会惊讶的发现,原 ...
- 【VS开发】C++异常处理操作
异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使用过异常,但是你会是一种习惯吗,不要老是想着当我打开一个文件的时候才用异常判断一下,我知道对你来说你喜欢用re ...
- Microservices
Microservices What are Microservices? What are Microservices - microservices.io Microservices - mart ...
随机推荐
- Server SAN:弄潮儿云计算时代
最初发表于<程序猿>2014年7每月一次. 4月30日本.Redhat公布1.71十亿收购Ceph开发商Inktank公司,加上之前2011年10月1.36十亿收购Gluster,Redh ...
- 使用jQuery和css3实现了仿淘宝ued博客左边的菜单切换动画
今天看到淘宝ued博客的左侧导航菜单的动画好,要使用jQuery和css3我做一个简单的示例,主要用途是实现jQuery 事件和css3 transition属性. 个元素来实现鼠标滑动到某个导航的背 ...
- Java实现 Base64、MD5、MAC、HMAC加密(转)
开始对那些基本的加密还不怎么熟练,然后总结了些,写了一个测试:支持 Base64.MD5.MAC.HMAC加密,长话短说,我们都比较喜欢自己理解,看代码吧! 采用的输UTF-8的格式... packa ...
- 简单实现Android平台多语言
这里,我们认识到两种语言.中国简体和繁体中国. 在res文件建议两个文件夹 values-zh-rCN values-zh-rTW 两个目录下都有一个strings.xml文件. 两个同名文件的字符串 ...
- ERROR 2003 (HY000): Can't connect to MySQL server on '10.16.115.101' (111)
ubuntu安装之后mysql,使用apt-get安装命令,默认为同意只本地访问 root@idata1:~/software# mysql -uroot -p123456 -h10.16.115.1 ...
- 开玩笑html5(五岁以下儿童)---绕地球月球,地球绕太阳运动(canvas实现,同样可以移动哦)
请珍惜劳动小编成果,这篇文章是原来小编,转载请注明出处. 速度的參数与真实速度有点差距.大家能够自行调整 <!DOCTYPE html> <html> <head> ...
- Node.js和PHP运行机制对比
为什么要用node.js它又有什么优势呢?一个新的技术被大家喜爱那么它就必然有它的优势,那么下面我们就来简单把它和php做一个对比 1 . Node.js 他用的是JavaScript引擎,那么注定它 ...
- MEF初体验之二:定义组合部件和契约
组合部件 在MEF中,一个组合部件就是一个组合单元,组合部件"出口"其它组合部件需要的服务并且从其它部件"进口"需要的服务.在MEF编程模型中,为了声明组合部件 ...
- ServletRequest接口召回总结
<body> <form action="LoginServlet" method="post"> User:<input typ ...
- ural 1932 The Secret of Identifier (容斥原理)
标题效果: 计算到n字符串. 精确到只是有一个不同的字符,两个不同的字符.三个不同的字符,四对不同的字符. IDEAS: 枚举状态. dp[i] [j] ...当前串取出 i 状态下的全部字符转化成十 ...