#pragma once 与 #if !defined 分开了

首先引用一段:

    _MSC_VER 定义编译器的版本。下面是一些编译器版本的_MSC_VER值(参见扩展阅读中的参考文献2的链接)
  MS VC++ 9.0 _MSC_VER = 1500
  MS VC++ 8.0 _MSC_VER = 1400
  MS VC++ 7.1 _MSC_VER = 1310
  MS VC++ 7.0 _MSC_VER = 1300
  MS VC++ 6.0 _MSC_VER = 1200
  MS VC++ 5.0 _MSC_VER = 1100
    其中MS VC++ 9.0就是Visual C++ 2008,MS VC++ 8.0就是Visual C++ 2005。版本名称上的的对应关系参见扩展阅读中的参考文献1的链接.

哈哈,再引用一段 (来自维基百科)

     使用#pragma once 代替 include 防范将加快编译速度,因为这是一种高阶的机制;编译器会自动比对档案名称或inode(中文就是索引节点,个人认为就是路径了)而不需要在标头档去判断 #ifndef 和 #endif。
然而,这种高阶的管理有好也有坏;设计者必须依赖编译器正确的管理 #pragma once。编译器如果犯错,例如没有辨认出在相同档案中的两个不同符号连结名称指标,此时编译会错误。

下面正题

    今天用VS 2008做一个VC++项目升级时突然发现项目中原本是有如下代码的:

#if !defined(AFX_PAGEPERIODTAG_H__58CA60B2_438A_11D2_A4E9_00A02474CBE5__INCLUDED_)
#define AFX_PAGEPERIODTAG_H__58CA60B2_438A_11D2_A4E9_00A02474CBE5__INCLUDED_

#if _MSC_VER >= 1000

#pragma once
#endif // _MSC_VER >= 1000

    而当我自己使用类向导生成时发现头文件中的对应部分仅生成了:

#pragma once

    好像 #pragma once是在VC++ 5.0 之后才出现的呢,要不怎么还得加上版本大于1000的判断呢. 加上之后应该就是为了兼容早期的编译器

    然后特地到VC 6.0 中试了一下,果然,上面代码是早期的VS生成的,貌似2008已经感觉不需要使用以前的旧机制了,可能2008自以为已经做的足够完美可以确保自己对系统的头文件重复包含编译时不会出错了吧(个人自己想的).

但是注意下面的了:

    #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况

    #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

    因此当你做的工程中有多个项目,或者因为其他情况需要引用并且拷贝同一个头文件,即存在两个完全相同头文件时,这时使用#if !defined + #pragma once 将会是一个不错的选择.

原文地址:https://www.cnblogs.com/dongzhiquan/p/1994582.html