关于inline这个关键字,听到强调得最多的是,它只是一种对于编译器的建议,而非强制执行的限定。

但事实上,即使这个优化最终由于函数太过复杂的原因没有达成,加上inline关键字(还有在类定义中直接定义的函数也相当于加上了inline关键字)还是会带来一些区别的。

参看C++11标准文档里面的描述:

A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline
specifier indicates to the implementation that inline substitution of the function body at the point of call
is to be preferred to the usual function call mechanism. An implementation is not required to perform this
inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules
for inline functions defined by 7.1.2 shall still be respected.

这里所谓的other rules具体如下:

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly
the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its
definition appears in the translation unit. — end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is
declared inline in one translation unit, it shall be declared inline in all translation units in which it appears;
no diagnostic is required. An inline function with external linkage shall have the same address in all
translation units. A static local variable in an extern inline function always refers to the same object.
A string literal in the body of an extern inline function is the same object in different translation units.
[ Note: A string literal appearing in a default argument is not in the body of an inline function merely
because the expression is used in a function call from that inline function. — end note ] A type defined
within the body of an extern inline function is the same type in every translation unit.

这里最关键的就是一个内联的函数,可以在多个cpp文件里面都有定义(回想一下普通函数如果这么干的话会有multiple definition的错误),标准明确了多个cpp文件的定义一定要一致,

但是编译器层面并不检查。

要理解An inline function with external linkage shall have the same address in all translation units. 这句话,可能需要对于链接过程有一定的理解。(深入理解计算机系统(csapp)第7章)。还可以看一下http://blog.copton.net/articles/linker/

这里简单表述就是,C++程序的每一个编译单元(cpp文件),编译完成之后生成一个.o文件,链接过程就是将这些.o文件合成一个可执行文件。

.o文件里是哪些内容呢?很多,关心的主要是以下几项

.text:代码段,包括这个cpp文件里定义的所有函数得到的字节码

.data:全局已初始化数据

.bss:全局未初始化数据

.reltext:引用的外部函数符号(比如我们会在引用外部函数或变量的时候有一个声明)

.reldata引用的外部变量

合成过程需要将各个.o文件的这几个部分聚合到一起:1重定位,聚合之后变量、函数都要重新排布,当然需要重定位2、将.reltext .data节里引用的外部函数,变量等赋予最终重定位之后的地址

看到这里,就能够大概理解,如果两个cpp文件恰好定义了同一个函数,会造成它们生成的.o文件在聚合的时候不知道取哪个定义,那么其它引用这个函数的地方也不知道重定位到哪,

所以会出现multiple definition的错误。而根据上面对于inline内联函数的表述,可以发现,它事实上赋予这种函数一个特别的属性,就是在多个.o文件里都定义了同一个内联函数的时候,

(这里当然不是成功内联的情形,因为那样的话根本只是插入代码段,连函数符号都没有了,更不用担心重定义了),链接器确保只从中选取一个作为最终的符号地址,这样就保证了

不会由重定义的情况出现了。

C++ inline weak symbol and so on的更多相关文章

  1. GNU的strong symbol和weak symbol

    首先,同样的原型的两个函数在连个不同的c文件中都有定义,把这两个c文件编译.连接在一起,也没有什么错误.原因就是因为,gcc中有一个strong symbol和weak symbol的概念.默认函数定 ...

  2. [原] inline operator delete & DLL boundary

    很久以前写在百度空间的这篇文章: [百度空间] [原] 全局operator delete重载到DLL 首先,纠正一个词“重载”,operator new/delete是替换(replacement) ...

  3. gcc/g++中weak弱符号及alias别名

    最近查看linux内核代码时,表现了一些编译器选项如__attribute_((weak)).__attribute__( (alias("target"))),一开始不了解,后来 ...

  4. C语言之强化,弱化符号weak

    一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初始化的全局变量是弱符号. 对于它们,下列三条规则使用: ① 同名的强符号只能有一个,否则编译器报"重复定义&q ...

  5. weak alias

    Weak Alias 跟 Weak Reference 完全没有任何关系,不过是我在看到 Weak Reference 的时候想到的而已. Weak Alias 是 gcc 扩展里的东西,实际上是函数 ...

  6. 弱符号__attribute__((weak))

    弱符号是什么? 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去使用普通的全局符号 ...

  7. __attribute__((weak, alias())))

    参考gcc的reference: 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去 ...

  8. 5.24 Declaring Attributes of Functions【转】

    转自:https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html 5.24 Declaring Attributes o ...

  9. GNU C/C++ __attributes__ GCC中的弱符号与强符号

    最近在看一些源代码,遇到了一些使用__attribute__修饰函数和变量的属性方面的代码,不是太了解,很是汗颜,再此做个总结:   GCC使用__attribute__关键字来描述函数,变量和数据类 ...

随机推荐

  1. 【CodeVS 1038】一元三次方程

    题意 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程. 给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的 ...

  2. mysql查询优化(持续更新中)

    1.        索引不会包含有NULL值的列 (1)   应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描 (2)   数据库设计时不要让字段的默认值 ...

  3. MySQL 加锁处理分析

    1    背景    1 1.1    MVCC:Snapshot Read vs Current Read    2 1.2    Cluster Index:聚簇索引    3 1.3    2P ...

  4. GIS软件列表

    3map:行星地球项目由3map驱动,这是一个自由软件,由Telstra宽带基金会创建并支持,提供客户端与服务器的能力以在线再现虚拟地球. Amein!:其界面介于ArcMap和UMN Mapserv ...

  5. hdu----(5056)Boring count(贪心)

    Boring count Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  6. HDUOJ-------2719The Seven Percent Solution

    The Seven Percent Solution Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  7. C++编程中const和#define的区别

    (1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使用.(2) 类型和安全检查不同 define宏没有类型,不做任何类型检查,仅仅是展开. const常量有具 ...

  8. springMVC 验证器

    采用Hibernate-validator来进行验证,Hibernate-validator实现了JSR-303验证框架支持注解风格的验证.首先我们要到http://hibernate.org/val ...

  9. Java 集合系列 15 Map总结

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  10. 3.1 关系数据库标准语言SQL综述

    一.SQL语言的特点 SQL结构查询语言 1.综合统一: 2.高度非过程化:不需要指定存储路径 3.面向集合的操作方式 4.以同一种语法提供两种使用方式:独立语言.嵌入式语言 5.语言简单,易学易用 ...