#ifndef 与 #program once 的区别(转)

摘要:
#pragmaonce方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受C/C++语言标准的支持,不受编译器的任何限制;而#pragmaonce方式却不受一些较老版本的编译器支持,一些支持了的编译器又打算去掉它,所以它的兼容性可能不够好。)的版本取消对#pragmaonce的支持。不过事实上,我手上的GCC3.4.2和GCC4.1.1仍然支持#pragmaonce,甚至没有deprecationwarning,倒是GCC2.95会对#pragmaonce提出warning。VC6及其以后版本亦提供对#pragmaonce方式的支持,这一特性应该基本稳定下来了。

转自http://hi.baidu.com/hrx20091001/item/ee70f7cc6d036d4ea9ba94e0

#ifndef 与 #program once 的区别

为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragmaonce方式。在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
方式一:
#ifndef__SOMEFILE_H__
#define__SOMEFILE_H__
......//声明、定义语句
#endif

方式二:

#pragmaonce
......//声明、定义语句

#ifndef的方式受C/C++语言标准支持。它不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含。
当然,缺点就是如果不同头文件中的宏名不小心“撞车”,可能就会导致你看到头文件明明存在,编译器却硬说找不到声明的状况——这种情况有时非常让人抓狂。
由于编译器每次都需要打开头文件才能判定是否有重复定义,因此在编译大型项目时,ifndef会使得编译时间相对较长,因此一些编译器逐渐开始支持#pragmaonce的方式。

#pragmaonce一般由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。你无法对一个头文件中的一段代码作pragmaonce声明,而只能针对文件。
其好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。大型项目的编译速度也因此提高了一些。
对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,这种重复包含很容易被发现并修正。

#pragmaonce方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受C/C++语言标准的支持,不受编译器的任何限制;而#pragmaonce方式却不受一些较老版本的编译器支持,一些支持了的编译器又打算去掉它,所以它的兼容性可能不够好。一般而言,当程序员听到这样的话,都会选择#ifndef方式,为了努力使得自己的代码“存活”时间更久,通常宁愿降低一些编译性能,这是程序员的个性,当然这是题外话啦。

还看到一种用法是把两者放在一起的:

#pragmaonce
#ifndef__SOMEFILE_H__
#define__SOMEFILE_H__
......//声明、定义语句
#endif

看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险,也无法避免不支持#pragmaonce的编译器报错,所以混用两种方法似乎不能带来更多的好处,倒是会让一些不熟悉的人感到困惑。

选择哪种方式,应该在了解两种方式的情况下,视具体情况而定。只要有一个合理的约定来避开缺点,我认为哪种方式都是可以接受的。而这个已经不是标准或者编译器的责任了,应当由程序员自己或者小范围内的开发规范来搞定。

btw:我看到GNU的一些讨论似乎是打算在GCC3.4(及其以后?)的版本取消对#pragmaonce的支持。不过事实上,我手上的GCC3.4.2和GCC4.1.1仍然支持#pragmaonce,甚至没有deprecationwarning,倒是GCC2.95会对#pragmaonce提出warning。
VC6及其以后版本亦提供对#pragmaonce方式的支持,这一特性应该基本稳定下来了。

免责声明:文章转载自《#ifndef 与 #program once 的区别(转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mpvue 使用echarts动态绘制图表(数据改变重新渲染图表)Commit Monitor–svn监控工具下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【PHP】PHPUnit单元测试利器:PHP Mock的使用方法

由于环境依赖关系,或者是特殊环境的构造要求,这就可能导致我们在测试环境下做验证是很困难的。 当我们无法直接使用的真实被依赖模块时,我们可以用“测试替身”(Test Double)来代替。这个测试替身不需要与真实的被依赖模块有相同的行为,它只需要提供和真实的被依赖模块有相同的API就行了。 PHPUnit提供的getMock($className)方法可以自...

RocketMQ消息至少一次(At least Once)投递和消费

至少一次(At least Once)指每个消息必须投递一次。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性。 生产者 在同步非顺序投递的时候,每次都是轮询到不同的队列: Message message = new Message("topic...

PHP生成条形码

首先找到强大的开源资料,在barcode官网下载barcodegen.1d-php5.v5.0.1.zip版本,然后解压文件放到你的Apache服务器的根目录下。 1 $text = $_GET['code']; 2 3 require_once('./barcodegen/BCGFontFile.php');...

iOS开发-单例模式

什么是单例模式?>是开发设计模式(共23种)中的1种>它可以保证在程序运行过程,一个类只有一个实例(一个对象),而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源>使用场合:在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次) iOS系统中的一些单例UIApplication(应用程序实例) NSNoti...

kafka入门

问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行“随机读写”的原因是什么? 3.kafka集群consumer和producer状态信息是如何保存的? 4.partitions设计的目的的根本原因是什么? 一、入门 1、简介 Kafka is a distributed,partitioned,rep...

VC++ 复制整个文件夹

CopyFile只能复制一个文件,要想复制整个文件夹的所有文件,需要遍历文件夹里面的文件。 MyFile.h #pragma once #include <string> #include <Windows.h> #include <iostream> #include <stdio.h> #include...