动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息

本月文章推荐
.打印Memo的文本信息.
.Bjarne:为什么一个空类的大小不.
.让CppWebBrowser响应回车健.
.对于SSH crc32 compensation att.
.如何在C/C++中调用Java.
.C++习题与解析(类和对象-07).
.学数学也要学点偷懒的技术.
.用CGI编写WEB查询系统.
.corba核心规范.
.PE文件格式分析心得.
.数据结构C语言实现系列——二叉树.
.C语言教程第七章:结构与联合.
.深入浅出Win32多线程程序设计之基.
.软件编码规范.
.生成静态连接库.
.迷宫.
.C++ Builder 初学问与答 (十).
.Win32下的几种串口通信编程.
.多层结构连接方式选择的分析.
.C语言教程第六章:指针.

More Effective C++:理解new和delete

发表日期:2008-3-8 |



  人们有时似乎喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。 

  当你写这样的代码:

string *ps = new string("Memory Management");
  你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。

  你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。

  函数operator new 通常这样声明:

void * operator new(size_t size);
  返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。(假如你喜欢,你能写一种operator new函数,在返回一个指针之前能够初始化内存以存储一些数值,但是一般不这么做。)参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。(有关operator new更多的信息参见Effective C++ 条款8至条款10。)

  你一般不会直接调用operator new,但是一旦这么做,你可以象调用其它函数一样调用它:

void *rawMemory = operator new(sizeof(string));
  操作符operator new将返回一个指针,指向一块足够容纳一个string类型对象的内存。

  就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。operator new所了解的是内存分配。把operator new 返回的未经处理的指针传递给一个对象是new操作符的工作。当你的编译器遇见这样的语句:

string *ps = new string("Memory Management");
  它生成的代码或多或少与下面的代码相似(更多的细节见Effective C++条款8和条款10,还有我的文章Counting object里的注释。):

void *memory = // 得到未经处理的内存
operator new(sizeof(string)); // 为String对象
call string::string("Memory Management") //初始化
on *memory; // 内存中

// 的对象

string *ps = // 是ps指针指向
static_cast<string*>(memory); // 新的对象
  注重第二步包含了构造函数的调用,你做为一个程序员被禁止这样去做。你的编译器则没有这个约束,它可以做它想做的一切。因此假如你想建立一个堆对象就必须用new操作符,不能直接调用构造函数来初始化对象。

  Placement new

  有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个非凡的operator new ,它被称为placement new。

  下面的例子是placement new如何使用,考虑一下:

class Widget {
 public:
  Widget(int widgetSize);
  ...
};

Widget * constrUCtWidgetInBuffer(void *buffer,int widgetSize)
{
 return new (buffer) Widget(widgetSize);
}
  这个函数返回一个指针,指向一个Widget对象,对象在转递给函数的buffer里分配。当程序使用共享内存或memory-mapped I/O时这个函数可能有用,因为在这样程序里对象必须被放置在一个确定地址上或一块被例程分配的内存里。(参见条款4,一个如何使用placement new的一个不同例子。)

  在constructWidgetInBuffer里面,返回的表达式是:

new (buffer) Widget(widgetSize)
  这初看上去有些生疏,但是它是new操作符的一个用法,需要使用一个额外的变量(buffer),当new操作符隐含调用operator new函数时,把这个变量传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:

void * operator new(size_t, void *location)
{
 return location;
}
  这可能比你期望的要简单,但是这就是placement new需要做的事情。究竟operator new的目的是为对象分配内存然后返回指向该内存的指针。在使用placement new的情况下,调用者已经获得了指向内存的指针,因为调用者知道对象应该放在哪里。placement new必须做的就是返回转递给它的指针。(没有用的(但是强制的)参数size_t没有名字,以防止编译器发出警告说它没有被使用;见条款6。) placement new是标准C++库的一部分(见Effective C++ 条款49)。为了使用placement new,你必须使用语句#include <new>(或者假如你的编译器还不支持这新风格的头文件名(再参见Effective C++ 条款49),<new.h>)。

  让我们从placement new回来片刻,看看new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。假如你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。假如你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。假如你想在一块已经获得指针的内存里建立一个对象,应该用placement new。

  (有关更多的不同的new与delete的观点参见Effective C++ 条款7和我的文章Counting objects。)

Deletion and Memory Deallocation

  为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。函数operator delete与delete操作符的关系与operator new与new操作符的关系一样。当你看到这些代码:


string *ps;
...
delete ps; // 使用delete 操作符
  你的编译器会生成代码来析构对象并释放对象占有的内存。

  Operator delete用来释放内存,它被这样声明:

void operator delete(void *memoryToBeDeallocated);
  因此, delete ps;

  导致编译器生成类似于这样的代码:

ps->~string(); // call the object's dtor
operator delete(ps); // deallocate the memory
// the object occupied

  这有一个隐含的意思是假如你只想处理未被初始化的内存,你应该绕过new和delete操作符,而调用operator new 获得内存和operator delete释放内存给系统:

void *buffer = // 分配足够的
operator new(50*sizeof(char)); // 内存以容纳50个char

//没有调用构造函数
...
operator delete(buffer); // 释放内存
// 没有调用析构函数
  这与在C中调用malloc和free等同。

  假如你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响:

// 在共享内存中分配和释放内存的函数 void * mallocShared(size_t size);

void freeShared(void *memory);
void *sharedMemory = mallocShared(sizeof(Widget));
Widget *pw = // 如上所示,
constructWidgetInBuffer(sharedMemory, 10); // 使用
// placement new
...
delete pw; // 结果不确定! 共享内存来自
上一篇:简单的职工管理系统(V1.1修改版)内含中文注释 人气:369
下一篇:简易实现网上动态信息发布 人气:239
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-8-20 25175 学生成绩管理查询系统 v2.
2008-8-20 乘风电影程序 v3.7 Acc
2008-8-20 乘风电影程序 v3.7 Sql
2008-8-20 XML文章系统 v1.08 build 080820
2008-8-20 老Y文章管理系统 v2.0 build 080
2008-8-20 OA企业智能办公自动化系统边缘特
2008-8-20 欣颐免费时尚发廊美发厅全站程序
2008-8-20 凌风简单留言板 v1.0
2008-8-19 久溜溜电影系统(免维护+小偷) v5
2008-8-16 iLaba Player(小喇叭播放器) v2.
2008-8-16 DoubleClickFix 鼠标双击修正工具
2008-8-16 CrystalCPUID 4.15.2.451
2008-8-16 VeryCD 电驴(easyMule) 1.0.4 Bu
2008-8-16 uTorrent 1.8 Build 11813 - Sta
2008-8-16 比特精灵(BitSpirit) v3.3.2.287
2008-8-16 StayInTune音叉 v1.0 破解版
2008-8-16 iChing《周易》汉化补丁 v1.0
2008-8-16 Starmap星空图v1.0汉化破解版
  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵