#ifndef vs #pragma once

前言


大家好,我是程序喵。在C或C++编程中,头文件的重复include是个很常见的问题,很多情况下会导致编译失败。


为了避免这种情况,一般有两种常用的方法:#ifndef和#pragma once。两种方法正常情况下都可以避免头文件的重复include,但是它们之间还有一些区别。本文将对这两种方法进行详细的对比分析,并给出代码示例。




知识点


#ifndef


先看使用示例:


// File: myheader.h

#ifndef __MYHEADER_H__
#define __MYHEADER_H__
// 我们的代码
#endif // __MYHEADER_H__


它的工作原理是检查一个特定的宏(本例中对应__MYHEADER_H__)是否已经被定义。如果这个宏还没有被定义,那么#ifndef和#endif之间的代码就会被编译;如果这个宏已经被定义,那么#ifndef和#endif之间的代码就会被忽略。


优点

  1. 它可以处理多个include的情况,即使一个头文件被include多次,也只会被编译一次。
  2. 它是C和C++标准的一部分,它可以用在所有的C和C++编译器上。


缺点

  1. 需要为每个头文件定义一个唯一的宏,每个头文件都要写这样的代码,比较麻烦。
  2. 如果头文件的名字或者路径发生改变,一般需要更新对应的宏,维护起来比较困难,容易出bug,如果两个头文件一不小心使用了一样的宏...


#pragma once

先看使用示例:

// File: myheader.h

#pragma once
// 我们的代码


#pragma once是一种特殊的预处理指令,它会告诉编译器只include这个头文件一次。


优点

  1. 使用起来非常简单,只需要在头文件的顶部添加一行#pragma once就可以。
  2. 即使文件名或者路径有改动,也无需定义新的指令名称,无需改动代码,维护成本低。
  3. 编译速度更快,这是一种高阶机制,部门编译器对此有优化。


缺点

  1. 它不是C/C++标准的一部分,虽然大部分的现代编译器都支持#pragma once,但是一些老的或者非主流的编译器可能不支持。



总结


#ifndef 属于C/C++标准的一部分,但使用起来麻烦,不利于维护。

#pragma once 使用起来简单,但不属于C++标准,非主流编译器可能不支持。


建议

目前主流编译器都已支持#pragma once,详见下图。如果你使用的是主流编译器,建议使用#pragma once,如果使用非主流编译器,或者非要追求标准,就使用#ifndef。




思考题

  1. 你平时使用哪种方式?有遇到过不支持#pragma once的编译器吗?


参考资料

  1. https://en.wikipedia.org/wiki/Pragma_once
  2. https://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards


0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
程序喵
下载 APP