【Effective C++】条款2:尽量以const,enum,inline替换#define

一.const替换#define 

#define的两个缺点:

  1. 不便于调试,编译器看到的是宏替换后的值,报错时显示也是替换后的内容,不便于定位错误
  2. 目标代码中出现多个替换后的内容。因为宏替换在预处理阶段完成,宏是不会进入记号表的。

 替换方案:使用const

//#define ARPECT_RATIO 1.653;
const double ArpectRatio = 1.653;

用#define替换常量时的两种特殊情况:

1.定义常量指针

//#define NAME "Effective C++"
const char* const Name = "Effective C++";

2.定义特定于类的常量

将常量作用域限制在类中,并确保只有一个常量的副本,就必须设置为类的静态成员

class GamePlayer
{//#define NUMTURNS 5;//这是无效的,#define只是无脑替换,无法将将作用域限制在类的内部static const int NumTurns = 5;//静态成员变量声明int scores[NumTurns];//使用静态成员变量
};

通常情况下,C++要求为所使用的任何东西提供定义,但类的静态整数类型常量(如bool,int,char)是个特例,可以声明时就给初值,在不取它们地址地址的情况下,可以直接使用,不用提供定义。

如果你在声明时给了初值,定义时就不能给值了。如果声明时没有给初值,定义时就能给值了。

class GamePlayer
{//#define NUMTURNS 5;//这是无效的,#define只是无脑替换,无法将将作用域限制在类的内部static const int NumTurns = 5;//静态成员变量声明//使用静态成员变量
};//const int GamePlayer::NumTurns = 6;//不允许的
const int GamePlayer::NumTurns;

二.enum替代#define

枚举类型的值可以在需要int的地方使用

class GamePlayer
{enum{NumTurns = 5};int scores[NumTurns];//使用枚举常量,枚举更像#define,不能取地址
};

三.inline替代#define

我们实现如下宏函数:

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) //f是一个函数

 尽管我们已经很小心了,为每个参数都加上了括号,但问题防不胜防:

int a = 5, b = 0;
CALL_WITH_MAX(++a, b);
CALL_WITH_MAX(++a, b + 10);

由于#define只是无脑替换,根据执行逻辑,第一个表达式a会被++两次,第二个a会++一次。这绝不是我们想要的结果,我们期望a无论如何只会++一次!!!

替代方案:模版+内联函数,既能获得宏的效率,又能保证函数行为可预测与类型安全

template<class T>
inline void CallWithMax(const T& a, const T& b)
{f(a > b ? a : b);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/199676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL窗口函数详解和实战(内含示例)

MySQL 窗口函数提供了跨与当前行关联的分组的计算能力。 窗口函数与聚合函数不同&#xff0c;聚合函数对每个分组进行计算并为每个分组返回一行&#xff0c;而窗口函数不会将每个分组输出到一行&#xff0c;而是将每个分组的计算结果合并到与之关联的行中。 目录 一、CUME_DIS…

【Maven】依赖管理

1. 依赖管理 1.1 依赖配置 依赖&#xff1a;指当前项目运行所需要的jar包。一个项目中可以引入多个依赖。 依赖引入步骤&#xff1a;在pom.xml中编写标签&#xff0c;在标签中使用引入坐标&#xff0c;定义坐标的 groupId、artifactId、version&#xff0c;最后点击刷新&…

html css 布局layout

弹性布局 display:flex; justify-content:space-between; — 水平分布【item之间有相同的边距&#xff0c;和容器之间没边距】justify-content: space-around; — item和item之间以及和容器之间都有边距align-items: center; — 垂直居中分布align-items:stretch; — 如果item…

17. 电话号码的字母组合 经典回溯组合题目

17. 电话号码的字母组合 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 17. 电话号码的字母组合 https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/ 完成情况&…

c题目16:写一个递归函数,计算N阶乘

每日小语 一生中&#xff0c;最光辉的一天并非功成名就的那一天&#xff0c;而是从悲叹与绝望中产生对人生挑战与勇敢迈向意志的那一天。——福楼拜 自己思考 这个小语呢&#xff0c;我目前还达不到&#xff0c;只是顺其自然&#xff0c;很多东西做起来很有动力&#xff0c;…

AIGC: 关于ChatGPT中对输出文本进行审核

违禁词 与 logit_bias 参数 前文&#xff0c;通过GPT的API实现了一个简单的聊天机器人, 当然也可以做一些内容审核相关的应用这里有一个非常核心&#xff0c;需要重点关注的一个方向&#xff0c;就是对于文本的审核 对于一些违禁词&#xff0c;我们需要准确的识别出来&#xf…

《opencv实用探索·十》opencv双边滤波的简单理解

1、引言 OpenCV中的双边滤波&#xff08;Bilateral Filtering&#xff09;是一种保持边缘清晰的滤波方法&#xff0c;它考虑像素的空间关系和像素值之间的差异。双边滤波对于去除噪声的同时保持图像的边缘非常有效&#xff0c;它也是一种非线性滤波。 双边滤波采用了两个高斯滤…

[Redis]基础入门

Redis入门 一、初识Redis Redis是一种键值型的NoSql数据库。 其中键值型&#xff0c;是指Redis中存储的数据都是以key、value对的形式存储&#xff0c;而value的形式多种多样&#xff0c;可以是字符串、数值&#xff0c;甚至是json。 NoSql则是相对于传统关系型数据库而言&a…

行业内卷严重到什么程度了?

一.内卷现状 最近大家都吐槽找工作难&#xff0c;确实很难。 不得不说&#xff0c;现在找工作的难度是以前的很多倍。甚至可以说地狱级都不为过。 以前只要简历一挂到网上&#xff0c;就有很多电话打过来。特别是在一线城市&#xff0c;各种类型企业的HR都来找&#xff0c;希…

Android wifi disable分析

总体流程 老套路基本不变&#xff1a; WifiSettings 通过 WifiManager 下cmd 给 WifiServiceWifiService 收到cmd后&#xff0c;先完成一部分列行检查&#xff08;如UID的权限、是否airPlayMode等等&#xff09;&#xff0c;之后将cmd下发给到WifiControllerWifiController 收…

Linux 环境变量

文章目录 环境变量概念查看环境变量设置环境变量代码获取环境变量补充说明 环境变量概念 定义 &#xff1a;环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。 个人理解&#xff1a;Linux下一切皆文件&#xff0c;在Linux中所用的指…

HTML5 基础总结

HTML5 HTML全称为超文本标记语言&#xff0c;是一种标记语言。由一系列标签构成&#xff0c;这些标签将分散的Internet资源链接成为了一个整体。 文档声明 HTML5之前 以SGML&#xff08;通用标准标记语言&#xff09;为标准 H5不再采用这个标准 声明方式比较简洁 语法特性 HTM…

在机器学习或者深度学习中是否可以直接分为训练集和测试集而不需要验证集?我的答案如下:

文章目录 一、训练集是什么&#xff1f;二、验证集是什么&#xff1f;三、测试集是什么&#xff1f;四、是否可以直接分为训练集和测试集而不需要验证集&#xff1f;总结 在机器学习和深度学习项目中&#xff0c;通常会将数据集划分为三个部分&#xff1a;训练集&#xff0c;验…

SpringMVC实验(四)——前后端分离下的数据交互

【知识要点】 前后端分离概念 前端开发不依赖与后端&#xff0c;二者均可独立发展。二者责任与分工明确&#xff0c;前端负责人机交互操作&#xff0c;后者负责仅提供数据服务&#xff0c;不再参与前端页面的跳转的控制。随着前端设备的多元化&#xff0c;前后端分离开发已经成…

UVM实现component之间transaction级别的通信

my_model是从i_agt中得到my_transaction&#xff0c;并把 my_transaction传递给my_scoreboard。在UVM中&#xff0c;通常使用TLM&#xff08;Transaction Level Modeling&#xff09;实现component之间transaction级别 的通信。 在UVM的transaction级别的通信 中&#xff0c;数…

在Word中移动页面主要靠导航窗格,有了它,移动页面就事半功倍

本文包括有关在Microsoft Word 2019、2016和Office 365中使用导航窗格移动页面以及复制和粘贴页面的说明。 如何设置导航窗格以重新排列页面 Microsoft Word并不将文档视为单独页面的集合,而是将其视为一个长页面。正因为如此,重新排列Word文档可能会很复杂。在Word中移动页…

【精选】ATKCK红队评估实战靶场二 (超详细过程思路)

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【ATK&CK红队评估实战靶场】 【VulnHub靶场复现】【面试分析】 &#x1f…

【.NET Core】Linq查询运算符(一)

【.NET Core】Linq查询运算符&#xff08;一&#xff09; 文章目录 【.NET Core】Linq查询运算符&#xff08;一&#xff09;一、概述二、筛选数据三、投影运算3.1 Select 3.2 SelectMany3.3 Zip3.4 Select 与 SelectMany 四、Set&#xff08;设置&#xff09;运算4.1 Distinct…

智能优化算法应用:基于堆优化算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于堆优化算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于堆优化算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.堆优化算法4.实验参数设定5.算法结果6.参考文献7.…

Verilog if语句阻断z状态传播

一、测试代码 设置两组输入输出&#xff0c;对比使用assign赋值语句与always if语句。 if_assign_test.v timescale 1ns / 1ps // // Engineer: wkk // Module Name: if_assign_test // module if_assign_test(input if_a_in,input if_b_in,input if_c_in,input if_d_in…