尽量以const、enum、inline替换 #define——条款02

条款02:尽量以 const, enum, inline替换 #define 文章摘要:本文建议优先使用const、enum和inline替代#define宏定义。const常量具有类型安全、调试友好和优化空间等优势;enum hack适用于类专属编译期常量;inline函数可避免宏函数的参数求值和优先级问题。虽然预处理器在条件编译中仍有作用,但应尽量减少对#define的依赖,转而使用更安全的现代C++特性如constexpr和模板。核心原则是让编译器而非预处理器处理更多工作,以提高代码的可靠性和可维护性。 阅读详情

        这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许 #define 不能被视为语言的一部分。

一、比如定义一个宏:

#define ASPECT_RATIO 1.653

        这个ASPECT_RATIO也许从未被编译器看见。也许在编译器开始处理源码之前就被预处理器移走了。于是记号名称ASPECT_RATIO有可能没进入记号表内,当你运用此常量但获得一个编译器错误信息时,可能会带来困惑,因为这个错误信息也许会提到1.653而不是ASPECT_RATIO。

    解决方法是用常量来替换宏:

        const double AspectRatio = 1.653

        作为一个语言常量,AspectRatio肯定会被编译器看到,当然就会进入记号表内。此外对浮点常量而言,使用常量可能比使用#define 产生的代码量少,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”可能导致目标码出现多份1.653,若改用常量AspectRatio绝不会出现相同情况。

二、另外有时候代码用宏来定义一个简单的函数,比如:

    #define RECTANGULAR_AREA(a, b) f(a*b)

    当然上述写法是有问题的,之前在面试题库中就找到过类似的问题,当“a”是一个(2+3)这种形式的值时就会出错。

    正确写法:

    #define RECTANGULAR_AREA(a, b) f((a) * (b))

这里可以写一个inline函数来替换到该宏,就是一个简单的乘法运算。

template<typename T>
inline T rectanglarArea(const T& a, const T& b) {
    return a*b
}

三、#define并不重视作用域。

        一旦宏被定义,它就在其后的编译过程中有效(除非在某处被#undef)。这意味#define不能提供任何封装性,没有所谓的private #define这样的东西。但是const成员变量是可以被封装的。

四、enum替换define场景

class GamePlayer {
private:
    static const int NumTurns = 5  //常量声明式
    int scores[NumTurns];          //使用该常量
    ...
};

        通常C++要求你对所使用的任何东西提供一个定义式,但如果它是个class专属常量又是static且为整数类型,则需特殊处理。只要不取它们的地址,你可以声明并使用它们而无需提供定义式。但如果取某个class专属常量地址或纵使你不取其地址而你的编译器去(不正确地)坚持要看到一个定义式,你就必须另外提供定义式如下:

const int GamePlayer::NumTurns; // NumTurns的定义

        上述这个式子是放在实现文件而非头文件。由于class常量已在声明时获得初值(例如先前声明NumTurns是设置为5),因此定义时不可用再设初值。

        旧式编译器也许不支持上述语法,不允许static成员在其声明式上获得初值。此时可改用所谓的“the enum hack”补偿做法。其理论基础是:“一个属于枚举类型的数值可权充ints被使用”,于是GamePlayer可定义如下:

class GamePlayer {
private:
    enum { NumTurns = 5 };
    int scores{NumTurns};
}

 

请记住

  • 对于单纯常量,最好以const对象或enums替换#defines。

  • 对于形似函数的宏(macros),最好改用inline函数替换#defines。

        关于宏定义,一般从C转C++的开发者来说用用#define的习惯,但是宏定义主要是编译器不会对其进行检查,之后盲目的将对应记号替换成设定的值,这就要求开发者要足够小心,另外出现由#define引起的问题也很难排查,所以在开发过程中尽量避免#define是很好的建议。

 

 

 

Effective C++条款 02:尽量以 const, enum, inline 替换 #define 文章目录条款 02:尽量以 const, enum, inline 替换 #define问题产生解决方法替换#defines的两种特殊情况1. 定义常量指针 (constantpointers)2. 定义class专属常量认识enum的理由行为实用 条款 02:尽量以 const, enum, inline 替换 #define 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#define 不被视为语言的一部分。那正是它的问题所在。 问题产生 例如下面代码: #define ASPECT_RA 阅读详情

相关推荐

保姆级教程:用Unity为麒麟系统打包Linux应用(含路径权限全攻略)

本文提供了一份详细的Unity跨平台开发指南,重点介绍如何在麒麟系统上打包和部署Linux应用。从开发环境配置、路径权限处理到性能优化和常见问题解决,全面解析了Unity项目在国产操作系统上的适配流程,帮助开发者高效完成跨平台应用开发。

weixin_28692867的博客 503

effective C++(第三版)读书笔记一——条款二:尽量以const,enum,inline替换#define

书中“宁可以编译器替换预处理”算是另一种提法,不过这个应该是概括性的说法吧 主要事项注意如下: 1用const double AspectRatio=1.653;代替#define ASPECT_RATIO 1.653 原因是预编译时define会被简单的替换,这样在编译时丢掉了ASPECT_RATIO,如果不正 当使用了ASPECT_RATIO编译时提示出错的可能只是...

weixin_30732825的博客 141

Part03 数据结构

本文介绍了CSP-S初赛中常见的高级数据结构及其实现,包括: 线性结构:双端栈、双端队列、单调队列、优先队列和ST表,重点分析了它们的特点、时间复杂度及典型应用场景。 集合与森林:并查集(带路径压缩和按秩合并)和树的孩子兄弟表示法,展示了多叉树转化为二叉树存储的方法。 特殊树结构:包括二叉堆、树状数组、线段树和字典树,详细说明了它们的构建、查询和更新操作,特别强调了线段树的递归实现和字典树的前缀匹配特性。 每种数据结构都配有核心C++代码实现,涉及数组模拟、动态规划和树形结构等编程技巧,适合算法竞赛选手快速

weixin_43863957的博客 1179

Effective C++阅读笔记条款01C++语言联邦,02const,enum,inline替换#define

条款1,C++不仅仅是一C语言加入了面向对象特性的高级语言。 发展到现在C++可被称为多重泛型编程语言,一个同时支持过称形式,面向对象形式,函数形式,泛型形式,元编程形式de语言。 如果要正确理解C++,最好将其视为一个语言联邦。该联邦由4个子语言模块组成。 C,Object-Oriented C++,Template C++,STL.具体内容根据字面意思大体了解即可。只有一点值得注意,迭代

720

Ubuntu技巧-Ubuntu远程访问之SSH反向代理

💡大家好,我是可夫小子,《小白玩转ChatGPT》专栏作者,关注AIGC、互联网和自媒体。要把内网的一台的Ubuntu服务器让外面也能访问,总共有三种可行的方案,前面已经介绍了两种方式,今天就来介绍更健壮稳定的方式——ssh反向代理。大概的框架图如下,今天就从服务器购买到设置,手把手的教程,让你花费100块以内,就拥有一个强大的「云服务器」。

可夫小子的频道 1151

使用cartographer纯定位替换amcl定位

经过实际使用,发现cartographer定位对于重定位的表现比amcl好。如果机器人的起始位置离原点较远,amcl很难自行重定位到正确的位置,只能手动修改初始位置。然而cartographer定位的表现则很好,在行驶一段距离或原地旋转一段时间后能够正确重定位。

XJ_75的博客 8313

条款01~02

01:视C++为一个语言联邦 C++是个多重范型编程语言multiparadigm programming language,一个同时支持过程形式procedural, 面向对象形式 object-oriented,函数形式 functional,泛型形式generic,元编程形式metaprogramming的语言。 简单方法就是将C++视为一个由相关语言组成的联邦而非单一语言。在其某个次语

王小东大将军的博客 335

知识图谱-KGE-语义匹配-双线性模型-2018:SimplE

【paper】 SimplE Embedding for Link Prediction in Knowledge Graphs 【简介】 本文是加拿大英属哥伦比亚大学的两位学者发表在 NIPS 2018 上的工作,文章提出了 SimplE(Simple Embedding)。这篇和前面一篇差不多,也是对 1927 年的 CP 进行改进(简化),传统CP为实体分配的两个向量是独立训练的,SimplE利用关系的逆在三元组打分函数中加上了一个对称项,使得每个实体的两个向量依赖学习,并且 SimplE 的复杂度随

u013250861的博客 957

effective C++ 3th 备忘1

2014-11-21 星期五 22:00:15  1、copy构造/copy赋值 copy构造函数被用来"以同型对象初始化自我对象",  copy assignment操作符被用来"从另一个同型对象中拷贝其值到自我对象" 1 2 3 4 5 6 7 8 9 10 11 cl

自由度 749

Windows原生环境配置Tensorflow使用GPU

本文讲解如何在Windows原生环境搭建可调用GPU设备进行计算的Tensorflow2.x环境。 区别于WSL,使用Windows原始环境作为开发环境。

天然玩家的博客 1496

加速访问Cloudflare的网站的解决方案

本文主要介绍了加速访问Cloudflare的网站的解决方案,希望能对大家有所帮助。通过软件计算得到最快的IP地址的效果图如下图所示,具体解决方案参考下文。 在这里插入图片描述 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

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

Effective C++条款02:尽量以const,enum,inline替换#define(Prefer consts,enums and inlines to #defines)

CltCj的博客 917

Qwen-Image(阿里通义千问)技术浅析(一)

Qwen-Image(阿里通义千问多模态模型)是阿里巴巴推出的视觉-语言多模态大模型,能够理解图像内容并完成复杂的跨模态任务。

m0_75253143的博客 673

Effective C++之条款02:尽量以const,enum,inline替换#define

声明: 文中内容收集整理自《Effective C++(中文版)第三版》,版权归原书所有。 本内容在作者现有能力的基础上有所删减,另加入部分作者自己的理解,有纰漏之处敬请指正。 条款02:尽量以const,enum,inline替换#define Prefer const, enums, and inlines to #includes. 这个条款或许改为“宁可以编译器替换预处理器”比较好...

HakunaMatata的博客 238

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

条款02:尽量以const,enum,inline 替换 #define

条款02:尽量以const,enum,inline 替换 #define1.定义一个常量 知识点: 1 宏函数和函数的区别 2 详解宏定义(#define) – 值得去看 我们常用define做什么:1.定义一个常量,2.定义一个宏 1.定义一个常量 当我们定义一个常量时,我们可以用以下方式: #define ASPECT_PATIO 1.653 我们知道编译器并没有看到ASPECT_PATI...

汤小萌的博客 521

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

条款02:尽量以const,enum,inline替换#define

#define ASPECT_RATION 1.653 书中说 #define或许不被视为语言的一部分ASPECT_RATION可能从未被语言看到,这个记号可能未被进入记号表,并且调试的时候错误信息也是1.653,而不是 ASPECT_RATION,如果 ASPECT_RATION被定义在一个非你所写的头文件的话,你肯定对1.653来自哪里,于是你将因为一个非你所写的头文件而浪...

qq_38635597的博客 245

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

条款 02:尽量以 const,enum,inline 替换 #define

条款 02:尽量以 const,enum,inline 替换 #define Prefer consts,enums,and inlines to #defines. 宁可以编译器替换预处理器 #define ASPECT_RATIO 1.653 也许 ASPECT_RATIO 不会被编译器感知,即可能提前被预处理器移走了,导致 ASPECT_RATIO 可能没进入记号表(symbol ta...

?.?的专栏 350

EffectiveC++详解:条款02-尽量以const,enum,inline替换#define

条款02-尽量以 const, enum , inline 替换 #define 1. #define 定义的名称无法追踪,不利于调试 2. 用常量替换 #define 的两种特殊情况 2.1 定义指针常量 2.2 类内常量成员 2.3 特殊情况 3. 用 inline 函数替代类函数的宏 (function-like marco) 总结 条款02-尽量以 const, enum...

神奇小海螺的博客 9732

条款 02:尽量以 const, enum, inline 替换 #define

文章目录一、用const替换#define1. 发生编译错误时,很难追踪2.没有封装性,不能限制作用域二、用enum代替#define三、用inline代替#define四、请记住 一、用const替换#define     #define 存在以下的问题: 1. 发生编译错误时,很难追踪 #define PI 3.14     如果运用了上面定义的常量时,由于在预编译时,所以用到了PI的地方全部都已经被替换掉了,若发生编译错误,错误信息只会提到3.14,而不是PI,非常的难以追踪

qq_43556776的博客 183

条款02: 尽量以const,enum,inline替换 #define

条款或许改为“宁可以编译器替换预处理”更好,因为或许#define不被视为语言的一部分。 对于如下的宏定义以常量替换: #define ASPECT_RATIO 1.653 const double AspectRatio = 1.653; 原因:ASPECT_RATIO从未被编译器看到;你所使用的名称可能并未进入记号表(symbol table),作为语言常量AspectRatio肯定...

hallå的博客 313

条款02:尽量以const,enum,inline替换#define(Prefer const,enum,inline to #define)

#define ASPECT_RATIO 1.653记号名称ASPECT_RATIO也许从未被编辑器看见;也许在编辑器开始处理源码之前被预处理器移走了。于是记号名称ASPECT_RATIO有可能没有进入记号表(symbol table)内。当用此常量获得一个编译出错信息,可能会带来困惑,因为这个错误信息也许会提到1.653而不是ASPECT_RATIO。解决之道是用一个常量替换上述的宏:

zzpalm的专栏 491

条款02:尽量以const,enum,inline替换#define——43

文章目录使用const替换#define——43使用enum替换——45inline替换——46总结——47 使用const替换#define——43 #define一般编译器是看不见的,想想这个情况:你调试别人的程序,程序里有语句: #define ASPECT_RATIO 1.653 编译错误提到1.653,而不是ASPECT_RATIO,因为编译器从记号表中没有找到ASPECT_RATIO这...

缇珞的博客 175
上一篇: 《Effective C++中文版》学习
下一篇: 确定对象被使用前已先被初始化——条款04
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值