#ifndef 和 #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之间的代码就会被忽略。
优点 #
- 它可以处理多个include的情况,即使一个头文件被include多次,也只会被编译一次。
- 它是C和C++标准的一部分,它可以用在所有的C和C++编译器上。
缺点 #
- 需要为每个头文件定义一个唯一的宏,每个头文件都要写这样的代码,比较麻烦。
- 如果头文件的名字或者路径发生改变,一般需要更新对应的宏,维护起来比较困难,容易出bug,如果两个头文件一不小心使用了一样的宏…
#pragma once #
先看使用示例:
// File: myheader.h
#pragma once
// 我们的代码
#pragma once
是一种特殊的预处理指令,它会告诉编译器只include这个头文件一次。
优点 #
- 使用起来非常简单,只需要在头文件的顶部添加一行
#pragma once
就可以。 - 即使文件名或者路径有改动,也无需定义新的指令名称,无需改动代码,维护成本低。
- 编译速度更快,这是一种高阶机制,部分编译器对此有优化。
缺点 #
- 它不是C/C++标准的一部分,虽然大部分的现代编译器都支持
#pragma once
,但是一些老的或者非主流的编译器可能不支持。
总结 #
#ifndef
属于C/C++标准的一部分,但使用起来麻烦,不利于维护。
#pragma once
使用起来简单,但不属于C++标准,非主流编译器可能不支持。
建议 #
目前主流编译器都已支持#pragma once
,详见下图。如果你使用的是主流编译器,建议使用#pragma once
,如果使用非主流编译器,或者非要追求标准,就使用#ifndef
。
思考题 #
- 你平时使用哪种方式?有遇到过不支持
#pragma once
的编译器吗?