C++(Qt)之尽可能延后定义式的出现时间

  1. 最近在看Scott Meyers的《Effective

    C++》改善程序与设计的55个具体做法(第三版),水平有限,有些东西没能完全理解,捡一些自己能理解的并很容易记住的点来分享下!有的是原文的内容的直接摘抄,敬请谅解!

    这条建议是:尽可能地延后定义式的出现时间。这么做的意义在于:可增加程序的清晰度并改善程序的效率。这对小程序来说可能体会的不深或者说影响不大,但是我们依然要保持良好的代码习惯和提高代码段的质量,不是吗?

    作者给的解释是:只要你定义了一个变量而其类型带有一个构造函数或者析构函数,那么当函数的控制流到达这个变量定义式时,我们要承受构造成本,当离开作用域时,需要承受析构成本。即使这个变量最终你没有去使用它,这么成本仍然需要消耗,所以这种情况最好不要发生!

    例如文中给的例子:

std::string encryptPasswoed(const std::string& password)
    {
        using namespace std;
        string encrypted;
        if (password.length()<MinimumPasswordLength)
        {
            throw...//抛出异常
        }
        ....
        return encrypted;
    }
  1. 上面的例子如果真抛出异常,那么变量encrypted就不会被使用,所以我们可以在异常判断之后再进行定义:
std::string encryptPasswoed(const std::string& password)
    {
        using namespace std;
        if (password.length()<MinimumPasswordLength)
        {
            throw...//抛出异常
        }
        string encrypted;
        ....
        return encrypted;
    }
  1. 这样是不是更合理一些呢?但是这么做也存在一些问题,下面我们看看文中是怎么说的。

    以上第二段代码虽然延后了定义的时间,但是却没有任何实参作为初值,这意味着会调用其默认(default)的构造函数,书中条款4解释了为什么“通过默认的构造函数赋初值的效率比直接在构造时指定初值的效率差”,所以我们应该避免让它调用构造函数赋初值。所以最好的做法是:

std::string encryptPasswoed(const std::string& password)
    {
        using namespace std;
        if (password.length()<MinimumPasswordLength)
        {
            throw...//抛出异常
        }
        string encrypted(password);//通过copy构造函数定义并初始化
        encrypt(encrypted);
        ....
        return encrypted;
    }
  1. 文中又补充道;我们不只应该延后变量的定义,直到非得使用该变量前的那一刻为止,甚至应该尝试延后这份定义直到给它初值实参为止。

    最后,文中还说明如果是在循环中遇到这种情况要怎么办的问题。

//方法A:定义于循环外
Widget w;
for(int i = 0; i < n ; i++)
{
    w = 跟i有关的某个值;
}

//方法B:定义于循环内
for(int i = 0; i < n ; i++)
{
    Widget w;//跟i有关的某个值;
}
  1. 问:这两种情况哪个比较好!分析下这两种写法的成本: A: 1个构造函数+1个析构函数+n个赋值操作 B:

    n个构造函数+n个析构函数 分析:

    如果classes的一个赋值成本低于一组构造加析构的成本,那么A会比较高效。根据(1)知道赋值成本比”构造”+”析构”的成本低,(2)正在处理的代码效率高度敏感的部分,否则选择B。一般情况下会选择A的写法。

  2. 最后,希望有更多的人能阅读并体会这书中的精髓,写出更高效更合理的代码!
时间: 2024-10-12 12:24:36

C++(Qt)之尽可能延后定义式的出现时间的相关文章

《Effective C++》之条款26:尽可能延后变量定义式的出现时间

<Effective C++> 条款26:尽可能延后变量定义式的出现时间 只要你定义了一个变量而其类型带有一个构造函数和析构函数,那么当程序的控制流到达这个变量定义式时,你便得承受构造成本:当这个变量离开作用域时,你便得承受析构成本.即使这个变量最终并未被使用,仍需耗费这些成本,所以你应该尽量避免这种情形. 对于"尽可能延后"的理解: 不只应该延后变量多的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初始实参为止.如果这样,不仅能够避免构造(析构

Effective C++ Item 26 尽可能延后变量定义式的出现时间

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率. 示例: //这个函数过早定义变量"encrypted" std::string encryptPassword(const std::string &password){ using namespace std; string encrypted; if(password.length() <

Effective C++:条款26:尽可能延后变量定义式的出现时间

(一) 那么当程序的控制流到达这个变量定义时,变承受构造成本:当变量离开作用域时,便承受析构成本. string encryptPassword(const std::string& password) { using namespace std; string encrypted; if(password.length() < MinimumPasswordLengt) { throw logic_error("Password is too short") } -//

[Effective C++ --026]尽可能延后变量定义式的出现时间

引言 每一次构造和析构都需要成本,因此我们在设计代码的时候,应该尽可能考虑到构造和析构的成本. 第一节 延后实现 考虑有以下的代码: 1 void encrypt(string& s); 2 string encryptPassword(const sting& password) { 3 string encrypted; 4 if (xxxxx) { 5 throw logic_error("xxxxxx"); 6 } 7 encrypted = password;

golang defer 延后执行什么

对于golang的defer,我们已经知道,defer定义的语句可以延后到函数返回时执行. 经常用在文件的关闭,锁的释放等场景中.而且defer定义的语句即使遇到panic也会执行.这样,可以执行必要的清理工作,甚至使用recover()捕获异常. 以前使用defer经常这样用: defer close() 或者 defer func(){ //do something... }() 本文介绍defer使用函数返回值(也是函数)作为延后执行内容时的情况. 请看例子代码: package main

【后序式的运算】

/* 后序式的运算 说明: 将中序式转换为后序式的好处是,不用处理运算子先后顺序问题,只要依序由运算式由前往后读取即可. 解法: 运算时由后序式的前方开始读取,遇到运算元先存入堆叠,如果遇到运算子,则由堆叠中取出两个运算元进行对应的运算,然后将 结果存回堆叠,如果运算式读取完毕,那么堆叠顶的值就是答案了,例如我们计算12+34+* 这个运算式 (也就 是(1+2)*(3+4) ): 读取 堆叠 1 1 2 12 + 3 3 33 (1+2后存回) 4 334 + 37 (3+4后存回) * 21

记一次备份发起时间延后问题

下午接到某业务DBA电话,某某业务资源比较繁忙,说备份发起时间由原来的12点延迟到13点半了. 经过查询确实备份时间一般在中午12点就发起,结果今天在1点半发起,1点半为上班时间再加上备份资源占用肯定高.经过业务组同意暂时先停掉该业务的job和策略.后接到反馈资源使用下来了. 问题暂时解决但需要查明原因为啥备份发起时间延后1.5小时. 查询备份发起时间结束时间等相关信息: COL STATUS FORMAT a9 COL hours FORMAT 999.999 COL START_TIME f

泛函编程(11)-延后计算-lazy evaluation

延后计算(lazy evaluation)是指将一个表达式的值计算向后拖延直到这个表达式真正被使用的时候.在讨论lazy-evaluation之前,先对泛函编程中比较特别的一个语言属性”计算时机“(strict-ness)做些介绍.strict-ness是指系统对一个表达式计算值的时间点模式:即时计算的(strict),或者延后计算的(non-strict or lazy).non-strict或者lazy的意思是在使用一个表达式时才对它进行计值.用个简单直观的例子说明吧: 1 def lazy

[js]变量声明、函数声明、函数定义式、形参之间的执行顺序

一.当函数声明和函数定义式(变量赋值)同名时 function ledi(){ alert('ledi1'); }; ledi(); var ledi = function (){ alert('ledi2'); }; ledi(); 执行顺序: var ledi: function ledi(){ alert('ledi1'); }; //预编译结束 ============== ledi(); ledi = function (){ alert('ledi2'); }; ledi(); 函数