教程学院
图像设计 多媒体类 机械制图 办公软件 操作系统 系统编程 网站编程 网页制作 数据库类 网络路由 网络工程 网络安全 考试认证
firefox火狐浏览器下载
酷网学院
CAD
AutoCad Cam350 ProEngineer GCcam MATLAB Unigraphics SolidWorks CAXA Solid3000 Cimatron EdgeCAM
系统
安全 防火墙 病毒 WinXP Win2003 Vista
数据库
编程
网络
精彩图库
  当前位置: 库库中文网 · 系统编程教程 · C++语言 · BCBC++基础

C++箴言:只要有可能就推迟变量定义

学院最新推荐文章
教程推荐
『C++箴言:只要有可能就推迟变量定义』如果文章有大量图片,显示会较慢,请等待图片下载完成
 
点击数: 更新时间:2006-4-26 

  在极大程度上,为你的类(包括类模板)和函数(包括函数模板)提供正确的定义是战斗的关键性部分。一旦你得到正确的结果,相应的实现很大程度上就是直截了当的。但是仍然有一些注意事项需要当心。过早地定义变量会对性能产生拖累。过度使用强制转换会导致缓慢的,难以维护的,被微妙的 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

  ·只要有可能就推迟变量定义。这样可以增加程序的清晰度并提高程序的性能。


作者:EQAL 来源:不详
】【关闭窗口
·上页:
·下页: 没有了
·当前位置: 库库中文网 · 系统编程教程 · C++语言 · BCBC++基础
相关文章
     系统编程教程 - BCBC++基础
普通教程C++中地指针(一) 简单指针
普通教程C++中地指针(三) 智能指针
普通教程C/C++ 运用程序路线图
普通教程C++程序设计从零开始(一)
普通教程C++程序设计从零开始(二)
普通教程C++程序设计从零开始(三)
普通教程C++程序设计从零开始(四)
普通教程C++程序设计从零开始(五)
普通教程C++程序设计从零开始(六)
普通教程C++程序设计从零开始(七)
普通教程C++程序设计从零开始(八)
普通教程C++程序设计从零开始(九)
精彩图片汇集
advertisement
关于站点 - 广告服务 - 联系我们 - 版权隐私 - 免责声明 - 合作伙伴 - 程序支持 - 网站地图 - 返回顶部
网站文本地图
版权所有:库库中文 2005-2007 欢迎各种媒体转载我们的原创作品[转载请注明出处]
copyright © 2005-2008 www.QQGB.com online services. all rights reserved. 蜀ICP备05015578
Template designed by Virus. Optimized for 1024x768 to Firefox,Opera and MS-IE6. Site powered by EQL.
红盾
热爱电脑,热爱生活
拥有电脑,拥有生命
让我们享受拥有电脑的时光