动态网站制作指南 [  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++教程 ]的信息

本月文章推荐
.C程序开发经典实例之8.
.C语言中可变参数的用法.
.启动新的应用程序.
.猜数游戏.
.《c语言程序设计》第三章: C语言.
.C++中要求(或禁止)对象产生于h.
.链表的c语言实现(七).
.DrawDib函数组的使用.
.VC的若干实用小技巧(一).
.怎样隐藏应用程序的任务栏图标.
.C语言常量与变量.
.内核模块的编译文件.
.C语言初学者入门讲座 第七讲 循环.
.MINI-FOOLFLY 游戏代码.
..
.在C程序中处理汉字.
.C++ 和 Delphi 的函数覆盖(Overr.
.C++程序设计从零开始之语句.
.服务器与客户机互传消息.
.2000年9月基础知识知识和C语言程.

只要有可能就推迟变量定义

发表日期:2008-3-8 |



  在极大程度上,为你的类(包括类模板)和函数(包括函数模板)提供正确的定义是战斗的要害性部分。一旦你得到正确的结果,相应的实现很大程度上就是直截了当的。但是仍然有一些注重事项需要当心。过早地定义变量会对性能产生拖累。
过度使用强制转换会导致缓慢的,难以维护的,被微妙的 bug 困扰的代码。返回一个类内部构件的句柄会破坏封装并将空悬句柄留给客户。疏忽了对异常产生的影响的考虑会导致资源的泄漏和数据结构的破坏。过分内联化(inlining)会导致代码膨胀。过度的耦合会导致令人无法接受的漫长的建构时间。 这一切问题都可以避免。

  只要有可能就推迟变量定义

  只要你定义了一个带有构造函数和析构函数的类型的变量,当控制流程到达变量定义的时候会使你担负构造成本,而当变量离开作用域的时候会使你担负析构成本。假如有无用变量造成这一成本,你就要尽你所能去避免它。

  你可能认为你从来不会定义无用的变量,但是也许你应该再想一想。考虑下面这个函数,只要 passWord 的长度满足要求,它就返回一个 password 的加密版本。假如 password 太短,函数就会抛出一个定义在标准 C++ 库中的 logic_error 类型的异常(参见 Item 54):

  

  // this function defines the variable "encrypted" too soon

  std::string encryptPassword(const std::string& password)

  {

   using namespace std;

  

   string encrypted;

  

   if (password.length() < MinimumPasswordLength) {

    throw logic_error("Password is too short");

   }

   ... // do whatever is necessary to place an

   // encrypted version of password in encrypted

   return encrypted;

  }

  

  对象 encrypted 在这个函数中并不是完全无用,但是假如抛出了一个异常,它就是无用的。换句话说,即使 encryptPassword 抛出一个异常,你也要为构造和析构 encrypted 付出代价。因此得出以下结论:你最好将 encrypted 的定义推迟到你确信你真的需要它的时候:

  

  // this function postpones encrypted’s definition until it’s truly necessary

  std::string encryptPassword(const std::string& password)

  {

   using namespace std;

  

   if (password.length() < MinimumPasswordLength) {

    throw logic_error("Password is too short");

   }

  

   string encrypted;

   

   ... // do whatever is necessary to place an

   // encrypted version of password in encrypted

   return encrypted;

  }

  这一代码仍然没有达到它本可以达到的那样紧凑,因为定义 encrypted 的时候没有任何初始化参数。这就意味着很多情况下将使用它的缺省构造函数,对于一个对象你首先应该做的就是给它一些值,这经常可以通过赋值来完成我已经解释了为什么缺省构造(default-constrUCting)一个对象然后赋值给它比用你真正需要它持有的值初始化它更低效。那个分析也适用于此。例如,假设 encryptPassword 的核心部分是在这个函数中完成的:

  

  void encrypt(std::string& s); // encrypts s in place

  那么,encryptPassword 就可以这样实现,即使它还不是最好的方法:

  

  // this function postpones encrypted’s definition until

  // it’s necessary, but it’s still needlessly inefficient

  std::string encryptPassword(const std::string& password)

  {

   ... // check length as above

  

   std::string encrypted; // default-construct encrypted

   encrypted = password; // assign to encrypted

  

   encrypt(encrypted);

   return encrypted;

  }

 

  一个更可取得方法是用 password 初始化 encrypted,从而跳过毫无意义并可能很昂贵的缺省构造:

  

  // finally, the best way to define and initialize encrypted

  std::string encryptPassword(const std::string& password)

  {

   ... // check length

  

   std::string encrypted(password); // define and initialize

   // via copy constructor

  

   encrypt(encrypted);

   return encrypted;

  }

  这个建议就是本 Item 的标题中的“只要有可能(as long as possible)”的真正含义。你不仅应该推迟一个变量的定义直到你不得不用它之前的最后一刻,而且应该试图推迟它的定义直到你得到了它的初始化参数。通过这样的做法,你可以避免构造和析构无用对象,而且还可以避免不必要的缺省构造。更进一步,通过在它们的含义已经非常明确的上下文中初始化它们,有助于对变量的作用文档化。

  “但是对于循环会如何?”你可能会有这样的疑问。假如一个变量仅仅在一个循环内使用,是循环外面定义它并在每次循环迭代时赋值给它更好一些,还是在循环内部定义这个变量更好一些呢?也就是说,下面这两个大致的结构中哪个更好一些?

  

  // Approach A: define outside loop // Approach B: define inside loop

  

  Widget w;

  for (int i = 0; i < n; ++i){ for (int i = 0; i < n; ++i) {

  w = some value dependent on i; Widget w(some value dependent on i);

  ... ...

  } }

  这里我将一个类型 string 的对象换成了一个类型 Widget 的对象,以避免对这个对象的构造、析构或赋值操作的成本的任何已有的预见。

  对于 Widget 的操作而言,就是下面这两个方法的成本:

  方法 A:1 个构造函数 + 1 个析构函数 + n 个赋值。

  方法 B:n 个构造函数 + n 个析构函数。

  对于那些赋值的成本低于一个构造函数/析构函数对的成本的类,方法 A 通常更高效。非凡是在 n 变得很大的情况下。否则,方法 B 可能更好一些。此外,方法 A 与方法 B 相比,使得名字 w 在一个较大的区域(包含循环的那个区域)内均可见,这可能会破坏程序的易理解性和可维护性。因此得出以下结论:除非你确信以下两点:(1)赋值比构造函数/析构函数对成本更低,而且(2)你正在涉及你的代码中的性能敏感的部分,否则,你应该默认使用方法 B。

  Things to Remember

  ·只要有可能就推迟变量定义。这样可以增加程序的清楚度并提高程序的性能。
上一篇:教你理解复杂的C/C++声明 人气:364
下一篇:Windows下的函数hook技术 人气:670
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-10-7 Web Wiz Forums(论坛系统) v9.53
2008-10-7 Web Wiz Forums(论坛系统) v9.53
2008-10-7 Web Wiz Forums(论坛系统) v9.53
2008-10-7 HDWiki v4.0.1 bulid 081007 UTF
2008-10-7 迅易评选投票管理系统 v10.0
2008-10-7 HDWiki v4.0.1 bulid 081007 GBK
2008-10-7 Bitrac单用户博客 v1.14 bulid 0
2008-10-7 OpenX(广告管理系统) v2.6.2 多国
2008-10-7 乐铺网店系统免费普及版 v3.41
2008-9-29 酷狗音乐(原KuGoo)2008 v5.310 正
2008-9-29 QQTab 1.1
2008-9-29 网络传送带 Net Transport 2.64a
2008-9-29 谷歌金山词霸v1.8
2008-9-29 TweakVI 1.0 Build 1090
2008-9-29 ACDSee Pro 2.5 Build 333 汉化绿
2008-9-29 Winamp v5.541(2189) 周明波简体
2008-9-27 CCleaner 2.12.651
2008-9-27 Mozilla Thunderbird 2.0.0.17 英
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成