尽可能延后变量定义式的出现时间——条款26

2023-11-06

        只要你定义了一个变量而其类型带有一个构造函数或析构函数,那么当程序控制流(control flow)到达这个变量定义式时,你便得承受构造成本;当这个变量离开其作用域时,你便得承受析构成本。即使这个变量最终未被使用,仍需耗费这些成本,所以你应该尽可能避免这种情形。 

        或许你会认为,你不可能定义一个不使用的变量,但话不要说得太早!考虑下面这个函数,它计算通行密码的加密版本而后返回,前提是密码够长。如果密码太短,函数会丢出一个异常:

// 这个函数过早定义变量“encrypted”
std::string encryptPassword(const std::string& password)
{
	using namespace std;
	string encrypted;
	if (password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}
	...                // 必要动作,能将一个加密后的密码置入变量encrypted内
	return encrypted;
}

        对象encrypted在此函数中并非完全未被使用, 但如果有个异常被丢出,它就真的没被使用。也就是说如果函数encryptPassword丢出异常,你仍得付出encrypted的构造和析构成本。所以最好延后encrypted的定义式,直到确实需要它:

// 这个函数过早定义变量“encrypted”
std::string encryptPassword(const std::string& password)
{
	using namespace std;
	if (password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}
	string encrypted;
	...                // 必要动作,能将一个加密后的密码置入变量encrypted内
	return encrypted;
}

        如果遇到循环的情况怎么办。如果变量只在循环内使用,那么把他定义于循环外并在每次循环迭代时赋值给它比较好,还是该把它定义于循环内?也就是说下面左右两个一般性结构,哪一个比较好?

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

// 方法B:定义于循环内

for (int i = 0; i < n; ++i) {
	Widget w(取决于i的某个值);
	...
}

        这里把对象类型从string改为Widget,以免造成读者对于“对象执行构造、析构、或赋值动作所需的成本”有任何特殊偏见。

        在Widget函数内部,以上两种写法的成本如下:

  • 做法A:1个构造函数+1个析构函数+n个赋值操作
  • 做法B:n个构造函数+n个析构函数

        如果classes的一个赋值成本低于一组构造+析构成本,做法A大体而言比较高效。尤其当n值很大的时候。否则做法B或许较好。此外做法A造成名称w的作用域(覆盖整个循环)比做法B更大,有时对程序的可理解性和易维护性造成冲突。因此除非:(1)你知道赋值成本比“构造+析构”成本低;

(2)你正在处理代码中效率高度敏感(performance-sensitive)的部分,否则你应该使用B。

请记住

  • 尽可能延后变量定义式的出现。这样做可增加程序的清晰度并改善程序效率。

        通常项目开发过程中,为了提高代码可读性,可维护性,所以基本上会选择上述"做法B"方案,就像我们设计程序的时候,当成员变量和成员函数不确定具体访问权限的时候,先用private修饰,即使后续修改也容易得多,不容易被乱用,导致其它问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尽可能延后变量定义式的出现时间——条款26 的相关文章

  • Effective C++

    条款01 视C 为一个语言联邦 将 视为一个由相关语言组成的联邦而非单一语言 条款02 尽量以const enum inline替换 define define处理与预处理阶段 而非编译阶段 因此此条款也可称为 宁可以编译器替换预处理器比较
  • Effective C++学习笔记——宁以传引用替换传值

    目录 一 传值效率可能会很低 二 传值可能发生割裂问题 三 适用于传值的情况和注意事项 相关博客 C 引用知识归纳 一 传值效率可能会很低 我们假设有这样两个类 class Human public string name string s
  • 编写new和delete时需固守常规——条款51

    条款50已解释什么时候你会想要写个自己的operator new和operator delete 但并没有解释当你那么做时必须遵守什么规则 这些规则不难奉行 但其中一些并不直观 所以知道它们究竟是些什么很重要 让我们从operator ne
  • 考虑写出一个不抛异常的swap函数——条款25

    swap是个有趣的函数 原本它只是STL的一部分 而后成为异常安全性编程 exception safe programing 见条款29 的脊柱 以及用来处理自我赋值可能性 见条款11 的一个常见机制 由于swap如此有用 适当的实现很重要
  • 确定你的public继承塑模出is-a关系——条款32

    如果你令class D Derived 以public形式继承class B Base 你便是告诉C 编译器 以及你的代码读者 说 每一个类型为D的对象同时也是一个类型为B的对象 反之不成立 你的意识是B比D表现出更一般化的概念 而D比B表
  • 运用成员函数模板接受所有兼容类型——条款45

    所谓智能指针是 行为像指针 的对象 并提供指针没有的机能 例如条款13曾经提及std auto ptr和tr1 shared ptr如何能够被用来在正确时机自动删除heap based资源 STL容器的迭代器几乎总是智能指针 无疑地你不会奢
  • 透彻了解inlining的里里外外——条款30

    Inline函数 多棒的点子 它们看起来像函数 动作像函数 比宏好得多 见条款2 可以调用它们又不需要蒙受函数调用所招致的额外开销 你还能要求更多吗 你实际获得的比想到的还多 因为 免除函数调用成本 只是故事的一部分而已 编译器最优化机制通
  • 《Effective C++》学习笔记——区分接口继承和实现继承

    派生类public继承自基类 其中函数均是接口继承 实现继承又分为缺省继承与强制继承 对应着虚函数与非虚函数 我们在做项目时 对于任何事物都要抱有先描述再组织的心态 因此 当描述事物为其构建框架尤其是存在继承 is a 关系时 一定要搞清楚
  • 在operator=中处理“自我赋值”——条款11

    自我赋值 发生在对象被赋值给自己时 class Widget Widget w w w 赋值给自己 这看起来有点愚蠢 但它合法 所以不要认定客户绝不会那么做 此外赋值动作并不总是那么可被一眼辨识出来 例如 a i a j 潜在的自我赋值 如
  • 将文件间的编译依存关系降至最低——条款31

    假设你对C 程序的某个class实现文件做了些轻微修改 注意 修改的不是class接口 而是实现 而且只改private成分 然后重新建置这个程序 并预计只花数秒就好 毕竟只有一个class被修改 你按下 Build 按钮或键入make 或
  • 条款13: 以对象管理资源

    结论 为防止资源泄漏 请使用RAII对象 它们在构造函数中获得资源并在析构函数中释放资源 两个常被使用的RAII classes分别是tr1 share ptr和auto ptr 前者通常是较佳选择 因为其copy行为比较直观 若选择aut
  • Effective C++改善程序与设计的55个具体做法笔记

    Scott Meyers大师Effective三部曲 Effective C More Effective C Effective STL 这三本书出版已很多年 后来又出版了Effective Modern C More Effective
  • 《Effective C++》 全书内容提炼总结

    个人博客地址 https cxx001 gitee io 本文阅读说明 孔子云 取乎其上 得乎其中 取乎其中 得乎其下 取乎其下 则无所得矣 对于读书求知而言 这句古训教我们去读好书 最好是好书中的上品 经典书 Effective C 就是
  • Effective C++ 学习笔记 《六》

    Item 6 Explicitly disallow the use of compiler generated functions you do not want 其实这一节的内容是和item5紧密相连的 上一节的核心围绕着编译器会自动生
  • 考虑virtual函数以外的其他选择——条款35

    假设你正在写一个视频游戏软件 你打算为游戏内的人物设计一个继承体系 你的游戏术语暴力砍杀类型 剧中人物被伤害或因其他因素而降低健康状态的情况并不罕见 你因此决定提供一个成员函数healthValue 它会返回一个整数 表示人物的健康程度 由
  • 写了placement new也要写placement delete——条款52

    placement new和placement delete并非C 兽栏中最常见的动物 如果你不熟悉它们 不要感到挫折或忧虑 回忆条款16和17 当你写一个new表达式像这样 Widget pw new Widget 共有两个函数被调用 一
  • 明智而审慎地使用多重继承——条款40

    当多重继承 multiple inheritance MI 进入设计景框 程序有可能从一个以上的base classes继承相同名称 如函数 typedef等等 那会导致较多的歧义机会 例如 class BorrowableItem 图书馆
  • 掌握 Effective C++ : 条款01

    背景 Effective C 是每个 C 程序员都应该读的经典之作 书中涵盖了 C 编程中的一系列最佳实践 包括了面向对象设计 模板 STL 异常处理等方面的内容 由于 C 的发展非常迅速 书中的某些内容可能已经过时 但依然是值得好好学习的
  • 复制对象时勿忘其每一个成分——条款12

    设计良好之面向对象系统 OO systems 会将对象的内部封装起来 只留两个函数负责对象拷贝 复制 那便是带着适切名称的copy构造函数和copy assignment操作符 我称它们为copying函数 条款5观察到编译器会在必要的时候
  • Effective C++——尽可能使用const

    const允许指定一个语义约束 也就是指定一个 不该被改动 的对象 而编译器会强制实施这项约束 只要保持某个值不变是事实 就应该说出来 以获得编译器的协助 保证不被违反 const与指针 注意const的写法 const char p p可

随机推荐

  • 鼠标滚动事件 - onmousewheel

    1 Jquery MouseWheel jquery默认是不支持支持鼠标滚轮事件 mousewheel jquery MouseWheel下载 https github com jquery jquery mousewheel blob m
  • 先后离开谷歌、雅虎后,梅姐的 AI 创业公司,再获两千万美金融资

    内容提要 硅谷一家创业公司 Lumi Labs 完成了近 2000 万美元的融资 这家鲜为人知的初创公司 凭什么能够拿下如此巨额的融资 这也许与其背后的大 boss 有关 它的创始人正是前雅虎 CEO 玛丽莎 梅耶尔 Marissa May
  • @JsonIgnoreProperties 解决实体中引用其他实体问题

    解决办法 json转换成的实体类加注解 JsonIgnoreProperties ignoreUnknown true 注意这是类级别的注解 JsonIgnore注解用来忽略某些字段 可以用在Field或者Getter方法上 用在Sette
  • _MSC_VER详细介绍

    MSC VER是微软的预编译控制 MSC VER可以分解为 MS Microsoft的简写 C MSC就是Microsoft的C编译器 VER Version的简写 MSC VER的意思就是 Microsoft的C编译器的版本 微软不同时期
  • 深度学习入门 ---- 张量(Tensor)

    文章目录 张量 张量在深度学习领域的定义 张量的基本属性 使用PyTorch 安装PyTorch 查看安装版本 创建张量 常用函数 四种创建张量的方式和区别 四则运算 张量 张量在深度学习领域的定义 张量 tensor 是多维数组 目的是把
  • 计算机配置内存容量怎么调,如何设置电脑虚拟内存,电脑虚拟内存设置多少最合理?...

    电脑虚拟内存是为了缓解CPU运行的压力而产生的一种新技术也可以理解为把电脑硬盘分出来一部分空间当作内存来使用 今天小编就为大家讲解下如何设置电脑虚拟内存 电脑虚拟内存设置多少最合理 希望对大家有所帮助 1 点击电脑左下角的开始菜单 找到控制
  • JavaScript中defer的作用

    JavaScript中defer的作用 Javascript中defer的作用是文档加载完毕了再执行脚本 这样会避免找不到对象的问题 defer是脚本程序强大功能中的一个 无名英雄 它告诉浏览器Script段包含了无需立即执行的代码 并且
  • Java浅拷贝和深拷贝

    Java Android 基础知识梳理 11 浅拷贝 Vs 深拷贝 Java对象数组深拷贝 java List复制 浅拷贝与深拷贝
  • C# 索引器(Indexer)

    C 索引器 Indexer 转自 http www runoob com csharp csharp indexer html 索引器 Indexer 允许一个对象可以像数组一样被索引 当您为类定义一个索引器时 该类的行为就会像一个 虚拟数
  • ibm服务器阵列卡与型号,IBM阵列卡介绍和服务器对阵列卡的支持情况

    ZDNetChina服务器站 芯片 组件配置技巧 目前IBM的阵列卡从控制的硬盘来说可以分成三大类 控制SCSI硬盘的SCSI RAID控制器 ServeRaid ServeRaid II ServeRaid 3L ServeRaid 3H
  • 【Leetcode】257. 二叉树的所有路径

    题目描述 题解 能用String解决的最好不要走StringBuilder 递归时注意空结点 null 回退和叶子结点判定回退 执行用时 9 ms 在所有 Java 提交中击败了30 66 的用户 内存消耗 39 1 MB 在所有 Java
  • Python 中的range(),arange()函数

    Python 中的range arange 函数 arange函数用于创建等差数组 使用频率非常高 arange非常类似range函数 会python的人肯定经常用range函数 比如在for循环中 几乎都用到了range 下面我们通过ra
  • 概率论中的重要不等式(Markov/Chebyshev/Jensen)

    1 Schwarz 不等式 对于任意的随机变量 和 均有 证明 假设 否则 有 所以不等式成立 我们有 即 2 Markov不等式 设随机变量 只取非负值 则对任意的 证明 固定正数 定义一个随机变量 易知 总成立 从而有
  • 1071svm函数 r语言_R语言机器学习之核心包e1071 - 数据分析

    R语言有很多包可以做机器学习 Machine Learning 的任务 机器学习的任务主要有有监督的学习方式和无监督的学习方式 有监督学习 在正确结果指导下的学习方式 若是正确结果是定性的 属于分类问题 若正确结果是定量的 属于回归问题 无
  • 软件设计模式(一)

    本章学习主要参照Datawhale开源学习及 大话设计模式 本项目结合 大话设计模式 这本书 总结了各种设计模式的基本概念 知识点和适用场景 先通过书中的案例 介绍了23种设计模式及其相关的代码示例 项目中有多种语言代码示例 本文主要采用P
  • Colorbox - a jQuery lightbox

    http www jacklmoore com colorbox http www jacklmoore com colorbox example5
  • C——结构体

    结构体 1 自定义类型 2 结构体 2 1 结构体类型说明 2 2 结构体变量的定义 2 3 结构体的初始化 2 4 结构体变量所占空间大小 2 5 结构体成员的引用 3 链表 3 1 处理动态链表所需的函数 3 2 指向自身的结构体类型
  • QScrollArea的简单使用

    当某个区域内的小部件尺寸超过了指定范围时 QScrollArea类提供了一个滚动区域 并生成滚动条 用于滚动显示区域内的所有小部件 关键代码 brief QScrollArea的简单使用 author xiaolei copyright v
  • stm32怎么用keil软件进行仿真?(必需掌握的技能)

    在做开发的前几年 基本上都没用仿真 有bug就尝试改程序 一边改一边调试 甚至都还不知道硬件仿真存在的价值 因为一直都没用过 而且很多芯片也不支持 直到有一次在做行车记录仪项目的时候 接触到了GRAIN公司的一款单片机 本来我打算是直接开干
  • 尽可能延后变量定义式的出现时间——条款26

    只要你定义了一个变量而其类型带有一个构造函数或析构函数 那么当程序控制流 control flow 到达这个变量定义式时 你便得承受构造成本 当这个变量离开其作用域时 你便得承受析构成本 即使这个变量最终未被使用 仍需耗费这些成本 所以你应