头文件不应该含有非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

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

  1. inline函数不报重定义错误浅析

    1 问题背景 关键字inline用于建议编译器在调用处展开被修饰的函数,但最终是否展开取决于编译器的行为 gcc配置参数-O0时不会进行编译优化,inline关键字不生效 gcc配置参数-O2时会进行 ...

  2. 关于inline函数和非inline函数

    今天在学习C++时看到了"在多个文件中使用类"这一小节,对于其中的内容不是十分理解,因此在此记录,并提出自己的一些看法. 如果有多个文件都需要 用到同一个类,那么就可以把这个类写在 ...

  3. c语言中关于不包含头文件string.h仍然可以使用strlen函数以及strlen函数计算数组时结果问题

    先说头文件string.h里的strlen函数 strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串 ...

  4. 习题 8.4 在本章第8.3.3节中分别给出了包含类定义的头文件student.h,包含成员函数定义的源文件student.cpp以及包含主函数的源文件main.cpp。请完善该程序,在类中增加。。。

    C++程序设计(第三版) 谭浩强 习题8.4 个人设计 习题 8.4 在本章第8.3.3节中分别给出了包含类定义的头文件student.h,包含成员函数定义的源文件student.cpp以及包含主函数 ...

  5. itoa 头文件 linux,Linux C编程 itoa()函数 atoi()函数

    今天在Ubuntu下编程,发现Linux内核中只有atoi()函数,被包含在stdlib.h头文件中,而没有itoa()函数,不过,itoa()函数的功能可以用sprintf()函数代替.如 int ...

  6. c语言中常用函数头文件,c语言中常用的函数和头文件

    头文件ctype.h 函数列表 函数类别函数目的详细说明 字符测试为字符和数字的isalnum 是否为isalpha字符 是否控制字符iscntrl 是否为数字isdigit 是否能够显示文字(空格除 ...

  7. 【C 语言】文件操作 ( 配置文件读写 | 框架搭建 | 头文件定义 | 头文件导入限制 | 兼容 C++ 语言 | 函数形参输入输出属性注释)

    文章目录 一.头文件定义 1.头文件导入限制 2.兼容 C++ 语言 3.函数形参输入输出属性 4.代码示例 一.头文件定义 1.头文件导入限制 头文件导入限制 : 防止头文件多次导入 , 将头文件的 ...

  8. c语言stdlib h常用函数,c语言中,头文件stdlib.h主要包含什么函数?

    stdlib.h里面定义了五种类型.一些宏和通用工具函数. 类型例如size_t.wchar_t.div_t.ldiv_t和lldiv_t: 宏例如EXIT_FAILURE.EXIT_SUCCESS. ...

  9. linux c语言sleep函数的头文件,C语言中的pause()函数和alarm()函数以及sleep()函数

    C语言pause()函数:让进程暂停直到信号出现头文件: #include 定义函数: int pause(void); 函数说明:pause()会令目前的进程暂停(进入睡眠状态), 直到被信号(si ...

  10. 单片机sleep函数的头文件_C语言中的sleep() 函数

    展开全部 关于sleep()函数在windows系统和linux系统下是两个不同的函数,差别较大,但功能是相同的,都是将进程挂起e68a8462616964757a686964616f31333337 ...

最新文章

  1. 第五轮学科评估再提“破五唯”
  2. 前端学习笔记(五)-JavaScript语法基本概念
  3. Linux学习笔记:touch新建文件、修改访问、改动时间
  4. 【Machine Learning实验2】 Logistic Regression求解classification问题
  5. android之Activity的生命周期
  6. cocos2dx + vs安装使用
  7. 使用Pitcher简化卫语句
  8. Seaborn——绘制统计图形
  9. 对话猿辅导:阿里云远程办公零信任落地创新安全
  10. ASP技巧:在Access数据库中重命名表
  11. 【Python】提升Python程序性能的好习惯
  12. 华三交换机配置access命令_H3C交换机配置命令大全
  13. 从一线技术人员到阿里合伙人,主导了去“IOE”,没有他,阿里只能给美国公司打工!...
  14. 动态加载并获取usercontrol生成的html
  15. Ehlib 单元格 图像绘制 代码
  16. Java+学生信息管理系统+GUI+文件
  17. 3dmax最基础的建模教程,初学者福利
  18. PDF编辑方法,怎么在PDF中添加图片
  19. 用python编写倒计时_python如何倒计时
  20. Qt之简易版网络调试助手

热门文章

  1. 关于IPV6审核被拒的完整分析
  2. 01 Django简介
  3. java----数据结构与算法----JavaAPI:java.util.Collection接口
  4. Scala For Java的一些参考
  5. WPF DataGrid 获取当前行某列值
  6. java内存堆栈的区别
  7. Crawler 爬虫
  8. homestead安装swoole扩展
  9. 有些东西需要深刻理解概念才行
  10. Entity Framework 复杂类型