头文件不应该含有非inline函数或对象的定义

头文件不应该含有非inline函数或对象的定义。....但是符号常量定义以及inline函数定义是特殊的定义。符号常量和inline函数可以被定义多次。  
   
  1.符号常量:在程序编译期间,在可能的情况下,符号常量的值会代替该名字的出现,这个替代过程被称为常量折叠(constant   folding)。   ....尽管理想情况下,一个具有初始值的常量可以被包含在多个不同的文件中,但是常量折叠使其变得并不必需,甚至在可执行文件只要出现一次就行。  
   
  是因为有常量折叠,符号常量才能在头文件中定义?  
   
  2.inline函数:如果编译器在调用点上没有内联该函数,则编译器会为该函数生成一个定义放到可执行文件中,如果在多个文件中生成同一函数的定义,则会产生一个不必要的、过大的可执行文件。  

这里涉及到编译器对inline和constant的实现.最常见的实现是(例如VC6),inline和constant的定义必须存在于每一个调用它们的CPP文件中,而且编译器不会帮你检查在两个CPP文件中的同名inline和constant是否是具有同样的值,所以大家都将它们放在头文件中. 可以想象,很有可能编译器直接将它们当作宏来处理了.  
  对于constant,在编译期间(准确地讲,应该是在预处理的时候),编译器会将它所遇到的所有constant的名字用constant的值来替换, 所以,虽然在每个CPP文件中都有constant的定义,但实际上,在最后的可执行文件中,并没有constant的存在.  
  对于inline,一个函数是否为inline,最终决定权在编译器手中.假如你在头文件中定义了一个inline,而该inline却被编译器枪毙了, 那么,可怜的编译器就会在每个存在该inline定义的CPP文件中生成一个全局函数,而且为了不产生冲突,这些函数都具有独一无二的名字.这样,你的可执行文件中就会多了一大堆具有奇怪名字并干着同样事情的函数:)
1.是因为有常量折叠,符号常量才能在头文件中定义?  
        不是因为有常量折叠,符号常量可以在头文件中定义,而是因为符号常量在不同的cpp文件中互相并不可见(类似于static全局变量,只在所处的文件中可见),所以即使名字相同也不会产生重复定义。  
        一般情况,在程序编译期间,编译器会为符号常量生成一个常量表,并用其值替换该名字(是在编译期间而不是预处理阶段,并进行类型检查,这是与宏的区别),并不为其分配空间,此动作被称为常量折叠。  
        但如果对常量进行了寻址(比如为其定义引用,或指针取其地址),编译器还是会为其分配空间。但是只能定义const引用或指针,所以其常量性也不受影响。  
   
  2.是因为inline函数的不能展开造成了“产生一个不必要的、过大的可执行文件”?  
        是的,因为若内联不成功,编译器会在每个引用该内联函数的cpp文件中,生成一个该函数定义。但实际实现中,有的链接程序会进行优化,使其只存在一个定义。一般来说,最好保证需内联的函数的能成功内联。  

        另外,定义一个内联函数只是向编译器申请内联,并不能保证一定能成为内联函数。内联函数的定义必须放在头文件中,因为必须让引用该函数的cpp文件都能见到该函数的定义,才能进行正确展开。


讨论出在http://bbs.csdn.net/topics/90349781

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值