C++inline&selectany

2018/03/27 c++

C++inline与selectany的使用

inline

  inline是C++中比较基础的一个修饰符,它的功能就是内联。但是我不准备介绍inline发挥内联功能的使用方法,而是准备介绍一下它作为一种能使函数和对象在头文件定义的修饰符的用法。

  众所周知,将函数或是全局变量的定义直接写在头文件中,是会报出fatal error LNK1169: 找到一个或多个多重定义的符号这样的错误的。然而,这个错误并不是由编译器报出的,而是由链接器报出的。因为我们在一个头文件中定义了某个函数或是变量后,一旦这个头文件被多个源文件包含,那么每个包含了这个头文件的源文件在被编译后所产生的.obj文件中都会有你在头文件中定义的函数或是变量的二进制符号。当链接器在链接时,就会发现有多个重复定义的符号,于是就会报错。而C++inline关键字就可以解决这个问题。在链接时,如果某个符号是使用inline修饰的,那么链接器会在多个编译单元(包含该符号定义的.obj文件中的该符号的定义部分)中任选一个与当前被调用处链接。inline修饰的函数编译产生的的多个符号定义中的static对象全都指向同一个对象

inline的用法

  在头文件中,你的全局变量、类中的静态对象(注意:不可将声明与定义分离放在头文件中)或是函数(非类中方法)的定义前直接加上inline即可。但是对于全局的const常量或是类中的方法来说,inline可以看做是默认带有的,不用加(msvc)。

selectany

  前几天,我遇到这样一个问题:一个定义在头文件中的全局常量,竟然在不同的源文件中调用,值是不同的(被多次地初始化了,且不同的源文件链接向了不同值的同名全局常量)。后来才发现使用__declspec(selectany)去修饰这个全局常量,就可以解决这一问题(仅限msvc编译器)。同样是在链接时,一旦某个符号是由__declspec(selectany)修饰的,链接器就会从多个相同的该符号的定义中选取一个链接,并删去其他重复的定义。于是就避免了这样的问题的产生。

selectany的用法

  使用也很简单,就是在头文件的全局作用域中的全局变量的定义前加上__declspec(selectany) extern修饰符。但是,类中的静态变量要把声明与定义分离,并在定义前加上__declspec(selectany)(不加extern)。且函数不能用__declspec(selectany)修饰(也没有必要)。

inlineselectany的比较

  selectanyinline相比,功能上更强大,但是却是微软的私货,没法通用。在效果上来说,inline只是保证链接不报错,你自己还要保证每份同名的符号定义的内容是一样的,不然会出蜜汁BUG。但是selectany就从根本上解决了这个问题,因为它只会保留一份符号定义,并将其他同名的符号定义在链接时删去。

Show Disqus Comments

Search

    welcome to visit my github

    creatorlxd's github

    Table of Contents