inline陷阱问题
2015-08-05 12:46
896 查看
在规范c++编程时遇到的,即类的文件定义
常规的对类的使用,在class.h对类进行生命,对于成员函数在class.cpp中定义,如下实现
这里面有个问题就是 对于内联成员函数,这种写法是链接不通过的
即下面这种情况
错误是
1>main.obj : error LNK2019: unresolved external symbol "public: int __thiscall person::backage(void)" (?backage@person@@QAEHXZ) referenced in function _main
看了一些博客,大概的问题在于,首先明白什么是内联函数,他的链接属性是什么
在c++03标准中
“ The inline keyword has no effect on the linkage of a function.“
也就是说,inline没有所谓的必须内部链接属性和外部链接属性
因为inline是直接嵌入代码的,那么 是否可以直接调用这个函数,实验一下
在ubuntu中
下面简单代码
使用gcc -S t.c -o t.s
发现t.s中并没有将这个函数内联
这是什么原因,网上将要将编译器优化
加上-O2 参数项
为了实验方便将c代码修改为
在main中发现就没有call函数了,而是内联成功了
所以有一点就是,inline只是请求编译器内联,是否内联不一定,除非加上编译参数强制内联。
然后下一个问题回到c++类中,为什么内联成员函数不能在其他文件中定义。
在ISO-Standard有这样一句话
在main中发现就没有call函数了,而是内联成功了
所以有一点就是,inline只是请求编译器内联,是否内联不一定,除非加上编译参数强制内联。
然后下一个问题回到c++类中,为什么内联成员函数不能在其他文件中定义。
在ISO-Standard有这样一句话
这样就符合上面的原则了
参考资料
/article/2802527.html
http://www.newsmth.net/bbscon.php?bid=335&id=146496
http://gcc.gnu.org/ml/gcc-prs/2002-11/msg01211.html
常规的对类的使用,在class.h对类进行生命,对于成员函数在class.cpp中定义,如下实现
main.cpp #include<iostream> #include "person.h" using namespace std; int main() { person p; p.setage(12); cout<<p.backage()<<endl; return 0; }
person.h #ifndef _PERSON_H_ #define _PERSON_H_ class person { public: void setage(int n); int backage(); private: int age; }; #endif
person.cpp #include "person.h" void person::setage(int n) { age=n; } int person::backage() { return age; }
这里面有个问题就是 对于内联成员函数,这种写法是链接不通过的
即下面这种情况
class person { public: inline void setage(int n); inline int backage(); private: int age; };
错误是
1>main.obj : error LNK2019: unresolved external symbol "public: int __thiscall person::backage(void)" (?backage@person@@QAEHXZ) referenced in function _main
看了一些博客,大概的问题在于,首先明白什么是内联函数,他的链接属性是什么
在c++03标准中
“ The inline keyword has no effect on the linkage of a function.“
也就是说,inline没有所谓的必须内部链接属性和外部链接属性
因为inline是直接嵌入代码的,那么 是否可以直接调用这个函数,实验一下
在ubuntu中
下面简单代码
t.c文件 inline void f() { int a; a++; } int main() { f(); return 0; }
使用gcc -S t.c -o t.s
发现t.s中并没有将这个函数内联
f: pushq %rbp movq %rsp, %rbp addl $1, -4(%rbp) popq %rbp ret main: pushq %rbp movq %rsp, %rbp movl $0, %eax call f movl $0, %eax popq %rbp ret
这是什么原因,网上将要将编译器优化
加上-O2 参数项
为了实验方便将c代码修改为
#include<stdio.h> inline int f(int a) { a++; printf("a=%d\n",a); return a; } int main() { int b=0; b=f(b); printf("b=%d\n",b); return 0; }汇编代码为
main: subq $8, %rsp movl $1, %edx movl $.LC0, %esi movl $1, %edi xorl %eax, %eax call __printf_chk movl $1, %edx movl $.LC1, %esi movl $1, %edi xorl %eax, %eax call __printf_chk xorl %eax, %eax addq $8, %rsp ret
在main中发现就没有call函数了,而是内联成功了
所以有一点就是,inline只是请求编译器内联,是否内联不一定,除非加上编译参数强制内联。
然后下一个问题回到c++类中,为什么内联成员函数不能在其他文件中定义。
在ISO-Standard有这样一句话
inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case. 并且有人对此做了研究,下面是对话
> File1.cc: > ----------------snip here---------------- > inline int foo (int x) { return x; } > > int bar() { return foo(2); } > ----------------snip here---------------- > > File2.cc: > ----------------snip here---------------- > inline int foo (int); > > int main() { return foo(1); } > ----------------snip here---------------- > > If I compile this using "g++ File1.cc File2.cc" I get a working program > that returns 1. If I compile it with "-O" enabled, I get a linker error: > > Unresolved text symbol "foo(int)" -- 1st referenced by /var/tmp//cckhU7pa.o. > > Without optimization the function "foo" in the first file isn't inlined. > But because it's used by "bar" it is put in the object file. With optimization > the function is inlined and doesn't appear explicitly in the object file of > the first file. Therefore, the linker error. > > In essence: The compiler does not need to put inline functions in the object > file. The compiler can just optimize them away. And because of that we have > paragraph 7.1.2.4.
在main中发现就没有call函数了,而是内联成功了
所以有一点就是,inline只是请求编译器内联,是否内联不一定,除非加上编译参数强制内联。
然后下一个问题回到c++类中,为什么内联成员函数不能在其他文件中定义。
在ISO-Standard有这样一句话
inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case. 并且有人对此做了研究,下面是对话
到此就明白了,在我上面的那个c++类中,如果main要调用内联的成员函数,那么在main所在的这个文件里必须要有内联函数的定义
所以修改为
main.cpp #include<iostream> #include "person.h" #include "person.cpp" using namespace std; int main() { person p; p.setage(12); cout<<p.backage()<<endl; return 0; }
这样就符合上面的原则了
参考资料
/article/2802527.html
http://www.newsmth.net/bbscon.php?bid=335&id=146496
http://gcc.gnu.org/ml/gcc-prs/2002-11/msg01211.html
相关文章推荐
- StringUtils方法全集
- 多听多想少说(转)
- windows下动态链接库的使用(实例)
- VC++自定义消息处理函数2
- java异常
- 编辑器类的介绍
- FreeImage裁剪示例
- Centost5.5_X64 Linux安装oracle 11.2.0.3 报错
- Servlet响应的中文字符集问题
- DWR如何获得返回对象
- Directionary 中Getfile中的通配符SearchPatern
- Android(java)学习笔记140:SpannableString类的使用
- 文件下载功能代码示例
- Keil4和Protues联调的做法
- LeetCode(95) Unique Binary Search Trees II
- nutch2.3命令参数解析
- 1037. Magic Coupon (25)
- leetCode 108.Convert Sorted Array to Binary Search Tree(将排序数组转换为BST) 解题思路和方法
- Java和C#的socket通信相关(转)
- 数据仓库与数据挖掘的OLAP技术----韩家炜教授的《数据挖掘概念与技术》学习笔记