zoukankan      html  css  js  c++  java
  • inline与lnk2001、lnk2019,鸡肋?

    inline函数居然出现了lnk2001、lnk2019,先贴代码。

    a.h
    #pragma once
    class A
    {
    public:

        inline void foo();
        void use_foo();
    };

     
    a.cpp
    #include "A.h"

    inline void A::foo()
    {

    }

    void A::use_foo()
    {
        foo();//此行注释掉会产生lnk2019错误
    }


    main.cpp
    #include "A.h"

    int main()
    {
        A a;
        a.foo();
        return 0;

    }

    看似简单的程序,揭示出inline的使用限制:

    1、在头文件中,类成员函数声明为inline时实现函数体,比如:
    #pragma once
    class A
    {
    public:

        inline void foo(){};//实现了函数体即便是空的
        void use_foo();

    };

    2、在头文件和源文件中分开实现,此类源文件中的“任意非inline函数续”需调用过此函数,然后其他源文件中才可用,此时链接时不会出现lnk2001 lnk2019错误。

    如:上面的a.cpp


    两种方法:

    第一种缺点是破坏封装,生成的库拿给别人用总不希望被看到函数体的实现吧

    第二种封装性好,别人只能看到声明,缺点是容易产生lnk错误。

    其实编译器尽量把头文件中的带实现的函数优化为inline,只要不带循环之类的就可以不用声明inline。

    inline只有在达到一定调用频率量级上才会显得快。比如:Release编译 /O2开启,第一种10亿次循环调用的差距大概在几十毫秒。第二种反而比非inline慢几到十几毫秒。

    结论:inline没必要使用

    如果是在头文件中实现类函数体,inline关键字不必使用,因为编译器默认会将头文件实现的类函数尽量优化为inline,而且这种破坏封装性,如果是编译给别人用的库还是算了。

    如果是在源文件中实现类函数体,inline关键字不能用,因为你不能保证该源文件一定需要调用该函数,可能造成其它源文件的lnk2001 lnk2019链接错误。

    如果追求极致性能又怕编译器不靠谱,请在头文件中声明inline且同时实现函数体,即便如此,编译器也会考量是否可编译为inline函数,并且前提是优化选项开启,比如VS的 /O2、g++的 -O2

    本人仅在vs2012 release下做过简单测试,欢迎交流。

  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3192179.html
Copyright © 2011-2022 走看看