美文网首页
[C++面试]宏相关问题

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

作者: TOMOCAT | 来源:发表于2021-09-19 18:02 被阅读0次

1. 宏常量与宏函数

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

#define <宏名> <字符串>
#define PI 3.1415926

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

2. 使用宏的原因?

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

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

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

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

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

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

// 不推荐
#define PI 3.14

// 推荐
const doule Pi = 3.14;

3.2 使用enum替换#define

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

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

class Student {
private:
    static const int num = 10;
    int scores[num];
};

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

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

class Student {
private:
    enum { num = 10 };
    int scores[num];
};

3.3 使用inline替换#define

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

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

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

#define MAX(a, b) ( { (a) > (b) ? (a) : (b); } ) // 求最大值

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

int a = 6, b = 5;
int max = MAX(a++, b);

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

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

7 // 正确的答案是 max 输出 6
8 // 正确的答案是  a  输出 7

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

int max = ( { (a++) > (b) ? (a++) : (b); } );  // a 被累加了2次!

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

#define MAX(a, b) ({ \
    __typeof(a) __a = (a), __b = (b); \
    __a > __b ? __a : __b; \
})

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

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

template<typename T>
inline T max(const T& a, const T& b)
{
    return a > b? a : b;
}

相关文章

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

    1. 宏常量与宏函数 C++中用#define <宏名> <字符串>命令定义宏,在代码中将字符串替换宏名出现的位置...

  • 面试常见问题 - 目录

    面试常见问题01 - C++相关(施工ing) 面试常见问题02 - 算法与数据结构(施工ing) 面试常见问题0...

  • ios 面试指南思维导图

    1.UI视图相关面试问题 2.Runtime相关面试问题 3.内存管理相关面试问题 4.Block相关面试问题 5...

  • iOS面试准备之思维导图(附资料)

    目录 1.UI视图相关面试问题 2.Runtime相关面试问题 3.内存管理相关面试问题 4.Block相关面试问...

  • c++相关面试

    [TOC] 基础 C语言里64位程序long类型的变量 长度是4还是8? - Brother Gao的回答 - 知...

  • iOS面试准备之思维导图

    目录 1.UI视图相关面试问题2.Objective-C语言特性相关面试问题3.Runtime相关面试问题4.内存...

  • iOS面试准备之思维导图

    目录 1.UI视图相关面试问题2.Objective-C语言特性相关面试问题3.Runtime相关面试问题4.内存...

  • 面试相关问题

    1.常用第三库(原理及优缺) AF GPUImage SDWebimage缓存实现原理?缓存内存结构数据结构?缓存...

  • C++相关问题

    1.用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数? 2.不用循环实现1+...

  • C++ 内存模型(1)--static

    面试过C++的同学都知道,面试官最喜欢问的问题之一就是C++内存模型问题。例如static 、堆、栈等网上对这方面...

网友评论

      本文标题:[C++面试]宏相关问题

      本文链接:https://www.haomeiwen.com/subject/vzkpgltx.html