在C/C++中,在使用预编译指令#include的时候,为了防止重复引用造成二义性(个人觉得这里二义性提的有点问题,觉得下面的补充可能理解好一些,有更好的解释可以帮我解答下哦。),通常有两种方式——

       第一种是#ifndef指令防止代码块重复引用(条件编译),比如说

#ifndef _HEADERNAME_H
#define _HEADERNAME_H

// contents of the header
...

#endif// _HEADERNAME_H

       当头文件第一次被包含时,它被正常处理,符号HEADERNAME_H被定义为1。如果头文件被再次包含,通过条件编译,它的内容被忽略。符号HEADERNAME_H按照被包含头文件的文件名进行取名,以避免由于其他头文件使用相同的符号而引起的冲突。

       第二种就是#pragma once指令,在想要保护的文件开头写入

#pragma once

// contents of the header
...

       1.#ifndef方式是C/C++语言的标准支持,也是比较常用的方式,#ifndef的方式依赖于自定义的宏名(例中的_CODE_BLOCK)不能冲突,它不光可以保证同一份文件不会被包含两次, 也能够保证不同文件完全相同的内容不会被包含两次。但,同样的,如果自定义的宏名不小心“重名”了,两份不同的文件使用同一个宏名进行#ifndef,那么会导致编译器找不到声明的情况(被编译器判定为重定义而屏蔽了)。

       #pragma once一般由编译器提供保证:**同一个文件不会被包含多次。这里所说的”同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。无法对一个头文件中的一段代码作#pragma once声明,而只能针对文件。**此方式不会出现宏名碰撞引发的奇怪问题,大型项目的编译速度也因此提供了一些。缺点是如果某个头文件有多份拷贝,此方法不能保证它们不被重复包含。在C/C++中,#pragma once是一个非标准但是被广泛支持的方式。

       2.编译速度:此外,由于编译器每次都需要打开头文件才能判定是否有重复定义,因此在编译大型项目时,#ifndef会使得编译时间相对较长,因此一些编译器逐渐开始支持#pragma once的方式(Visual Studio 2017新建头文件会自带#pragma once指令)。

       3.兼容性:#pragma once方式产生于#ifndef之后。#ifndef方式受C/C++语言标准的支持,不受编译器的任何限制;而#pragma once方式有些编译器不支持(较老编译器不支持,如GCC 3.4版本之前不支持#pragmaonce),兼容性不够好。#ifndef可以针对一个文件中的部分代码,而#pragma once只能针对整个文件。相对而言,#ifndef更加灵活,兼容性好,#pragma once操作简单,效率高。

补充:同一个文件被include多次的危害:

       (1)防止重复定义的错误;

       (2)如果这个头文件变化,那么所有include这个文件的源文件都需要重新编译,即使没有去使用里面的任何内容

参考链接:

#pragma once与#ifndef的区别_每天学一点!的博客-CSDN博客_#pragma once和#ifndef

#pragma once用法总结_大山喵的博客-CSDN博客_#pragma once

怎样防止头文件被重复包含?(两种方式)以及它的影响_阿狸茜茜的博客-CSDN博客_头文件重复包含

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐