#pragma once 与 #ifndef #define …#endif 的区别

  C/C++ 中有以下两种方式可以避免同一个文件被 #include多次。

  在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。

  方式一:










  这是 C++ 中的宏定义,通过宏定义避免文件多次编译。所以在所有支持 C++  语言的编译器上都是有效的。如果写的程序要跨平台,最好使用这种方式。

 

  #ifndef 的方式依赖于宏名字不能冲突,这不仅可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。

  另外,为了保证不同头文件中的宏名不冲突,故采取类似于 _FILE_H_ 的取名方式。其中,file.h 为当前头文件名。

  该方式的缺点就是,如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况。但我们可以通过特殊的宏的取名方式来避免名称冲突问题,于是其缺点也就不复存在了,进而#ifndef方式就更常用了。

  方式二:




  这个是编译器相关,就是说在这个编译系统上能用,但是不能保证在其他编译系统一定能用。不过现在基本上已经是每个编译器都支持该定义了。

  编译器提供保证,同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。于是不必再费劲想个宏名了,当然也就可以避免宏的名字冲突问题了。

  而这种方法的缺点是,如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

  下面,我们简单比较下以上两种方式的一些其他区别。

  使用 #ifndef 的话,编译器每次看到 #include 这个文件都需要读入该文件,解析代码;而使用 #pragma once 编译器根本不会重复打开文件, 大大提高了效率。例如,











































  头文件 Test1.h 中用宏来避免重复,头文件 Test2.h 中用 #pragma once 来避免重复。编译 Test.cpp,将需要打开 Test1.h 两次,第一次发现宏__TESTONE_H_ 没有定义,接着就处理宏定义;第二次打开 Test1.h 时,发现宏 __TESTONE_H_ 已经定义过了,编译器就会略过宏定义部分,直到处理完 Test1.h 末尾的 #endif。

  而由于头文件 Test2.h 使用 #pragma once 来避免重复定义的,在编译Test.cpp 的过程中,Test2.h 只会被打开一次,也就是处理到第3行的时候。因为 Test2.h 用的是 #pragma once,所以在处理完第3行后,编译器已经知道包含了一次 Test2.h,在编译器处理第4行代码时,发现 Test2.h 已经包含过了,忽略掉第4行代码,也就不需要再次打开 Test2.h 进行判断了。

  另外,使用 #pragma once 的代码更简洁,重要的是它避免了头文件标号,如__header_h__ 的 重定义或者 #endif 包含范围错误的情况。

  参考如下:

  http://mxdxm.iteye.com/blog/592542

  http://pppboy.blog.163.com/blog/static/3020379620106130528324/

发表评论

电子邮件地址不会被公开。 必填项已用*标注