if!defined与pragma once

来源:互联网 发布:抢红包软件 编辑:程序博客网 时间:2024/05/21 08:43

两者的共同点都是为了避免同一个文件被include多次,但是各有千秋。

在用VC6.0向导生成的头文件中,经常可以看见如下的代码段: 

#if !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_) 
#define AFX_RESIZABLELAYOUT_H__INCLUDED_ 

#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 

...  

#endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)

_MSC_VER  定义编译器的版本,下面是一些编译器版本的_MSC_VER值:

  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是编译相关的,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过现在基本上已经是每个编译器都有这个定义了。
(2)#ifndef / #define / #endif是C++语言相关的,它是通过C++语言中的宏定义来避免头文件被多次编译的。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。

使用#pragma once 代替 include 方法将加快编译速度,因为这是一种高阶的机制;编译器会自动比对档案名称或inode(中文就是索引节点,个人认为就是路径了)而不需要在标头档去判断 #ifndef 和 #endif。

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

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

ifndef能保证如果一个文件被重复放在了不同的地方时编译也不会出错。而如果出现一个文件被重复放到了不同地方,且都被包含的话,仅仅使用#pragma once还是会出现编译错误的。

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

0 0