前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[C++面试]宏相关问题

[C++面试]宏相关问题

作者头像
TOMOCAT
发布2021-12-16 09:46:53
7110
发布2021-12-16 09:46:53
举报

1. 宏常量与宏函数

C++中用#define <宏名> <字符串>命令定义宏,在代码中将字符串替换宏名出现的位置。定义宏的方式根据是否包含参数可以分为两种:

代码语言:javascript
复制
#define <宏名> <字符串>
#define PI 3.1415926

#define <宏名>(<参数列表>) <宏体>
#define A(x) x

2. 使用宏的原因?

在预处理阶段的宏替换仅仅是将目标字符串替换宏名,在代码中对宏的使用必须极其谨慎,否则很容易写出有问题的程序。定义宏的主要有两个场景:

  • 通过宏定义常量:在常量变更时仅需要修改宏的定义而不需要修改所有使用到常量的位置
  • 带参数的宏可以减少系统调用函数的开销:对于一些特别简单的函数而言,函数的调用开销不可忽视,带参数的宏在预处理阶段就进行了宏展开,提高了程序的运行效率
  • 带参数的宏可以实现模板功能

3. C++是否应该避免使用宏,如何避免使用宏?

C++原则:尽量使用constenuminline替换#define的使用,防止编译错误不够明朗,同时加强编译期间的类型检查,提高代码健壮性和可读性。

3.1 使用const替换#define定义常量

程序编译分为预处理、编译和链接三个阶段。#define是不被视为语言的一部分,在预处理阶段就会进行宏展开替换所有的宏,因此进入第二步编译阶段是如果遇到了编译错误,那么错误信息可能会提到3.14而不是PI,导致错误信息不够明朗。

代码语言:javascript
复制
// 不推荐
#define PI 3.14

// 推荐
const doule Pi = 3.14;
3.2 使用enum替换#define

我们无法使用#define创建一个class专属常量,因为#define并不重视作用域。

对于class内定义常量,我们通常使用static+const的方式定义:

代码语言:javascript
复制
class Student {
private:
    static const int num = 10;
    int scores[num];
};

const int Student::num; // static 成员变量,需要进行声明

如果不想外部获取到class专属常量的内存地址,可以使用enum的方式定义常量(因为取一个enum的地址是不合法的):

代码语言:javascript
复制
class Student {
private:
    enum { num = 10 };
    int scores[num];
};
3.3 使用inline替换#define

通常使用宏定义函数主要是出于如下考虑:

  • 实现模板功能
  • 减少函数调用带来的开销

另外一个常见的 #define 误用情况是以它实现宏函数,它不会招致函数调用带来的开销,但是用 #define 编写宏函数容易出错,如下用宏定义写的求最大值的函数:

代码语言:javascript
复制
#define MAX(a, b) ( { (a) > (b) ? (a) : (b); } ) // 求最大值

这般长相的宏有着太的缺点,比如在下面调用例子:

代码语言:javascript
复制
int a = 6, b = 5;
int max = MAX(a++, b);

std::cout << max << std::endl;
std::cout << a << std::endl;

输出结果(以下结果是错误的):

代码语言:javascript
复制
7 // 正确的答案是 max 输出 6
8 // 正确的答案是  a  输出 7

要解释出错的原因很简单,我们把 MAX 宏做简单替换:

代码语言:javascript
复制
int max = ( { (a++) > (b) ? (a++) : (b); } );  // a 被累加了2次!

在上述替换后,可以发现 a 被累加了 2 次。我们可以通过改进 MAX 宏,来解决这个问题:

代码语言:javascript
复制
#define MAX(a, b) ({ \
    __typeof(a) __a = (a), __b = (b); \
    __a > __b ? __a : __b; \
})

简单说明下,上述的 __typeof 可以根据变量的类型来定义一个相同类型的变量。改进后的 MAX 宏,输出的是正确的结果,max 输出 6,a 输出 7。

虽然改进的后 MAX 宏,解决了问题,但是这种宏的长相就让人困惑。我们可以用template inline的方式,写出短小的函数:

代码语言:javascript
复制
template<typename T>
inline T max(const T& a, const T& b)
{
    return a > b? a : b;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021/9/19 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 宏常量与宏函数
  • 2. 使用宏的原因?
  • 3. C++是否应该避免使用宏,如何避免使用宏?
    • 3.1 使用const替换#define定义常量
      • 3.2 使用enum替换#define
        • 3.3 使用inline替换#define
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档