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下做过简单测试,欢迎交流。

  • 相关阅读:
    任务26:dotnet watch run 和attach到进程调试
    我心中的ASP.NET Core 新核心对象WebHost(二)
    任务25:IHostEnvironment和 IApplicationLifetime介绍
    跨域之jsonp
    H5之拖拽
    h5学习之表单
    canvas之五角星的绘制
    canvas学习之初级运用
    js中常见继承方式
    this指针的使用场景
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3192179.html
Copyright © 2011-2022 走看看