现代C和C ++编译器支持非标准#pragma once
预处理程序指令,它与经典标题保护程序的用途相似:
#ifndef hopefully_unique_identifier_that_doesnt_hurt_the_code
#define hopefully_unique_identifier_that_doesnt_hurt_the_code
// some code here
#endif
我知道的一个问题是,经典的方法是,一旦你包含了一个标题,你必须#undef
标题保护宏再次包含它(这样做,对我来说,这是一个主要的代码味道,但这不是重点。 #pragma once
方法会出现同样的问题,但不允许多次包含标题。
经典方法的另一个问题是,您可能会意外地在不相关的地方定义相同的宏,因此要么不包括预期的标题,要么做一些其他令人讨厌的东西,我无法想象。这在实践中相当容易避免,通过遵守某些约定,例如将宏基于类似UUID的对象(即随机字符串)或(不太理想的方法),基于文件的名称,它们在
在现实生活中,我很少遇到任何这些潜在问题,所以我并不认为它们是主要问题。
#pragma once
我能想到的唯一潜在的现实生活问题是,它不是标准的东西 - 你依赖的东西可能无处不在,即使在实践中,它存在于任何地方(*)。
那么,除了我已经提到的问题之外,#pragma once
还存在哪些潜在的问题?我是否过于相信在实践中,无处不在?
(*)只有少数人使用的一些次要编译器,被排除在外。
答案 0 :(得分:8)
使用#pragma once
时遇到的一个问题是包含位于多个位置的同一文件。对于#pragma once
,它被认为是不同的,而不是#ifndef/#define
后卫。
答案 1 :(得分:4)
到目前为止,我使用过一套不错的编译器:
唯一不支持#pragma once
的编译器是IBM XLC编译器,它甚至不支持C ++ 11,所以我不感兴趣。如果您需要使用Blue Gene / Q上的IBM XLC Compiler,那么就不能使用#pragma once
。
很久以前,某些编译器不理解include guard成语,并且会重复打开头文件,但却发现预处理器将内容减少为空。使用这些编译器,使用#pragma once
可以提高编译时间。但是,这已在主要编译器中实现,因此现在没有任何区别。
也许您的嵌入式系统有一些特殊的编译器。那个人可能无法使用#pragma once
。
一般情况下,我更喜欢#pragma once
,因为当您复制头文件以通过复制或扩展类进行增量重构时,您不能忘记更改包含保护宏的名称。
因此,除了某些编译器之外,我不知道您对#pragma once
有任何难题。
答案 2 :(得分:4)
在使用#pragma once
时,您放弃了可移植性。您不再编写C或C ++,而是允许将其作为编译器扩展。
如果您的代码定位到不同的平台,那么可能会让您头疼。
因为这个原因,我从不使用它。
鉴于文件的名称和位置是唯一的,我将其用作我的包含守卫。此外,因为我过去的目标是非常老的预处理器,所以我习惯使用
#if !defined(foo)
#define foo 1
/*code*/
#endif
自1996年以来我所遇到的每个平台都有效。