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

  • 相关阅读:
    Js计算时间差(天、小时、分钟、秒)
    [原创]chromium源码阅读-进程间通信IPC.消息的接收与应答
    loki之内存池SmallObj[原创]
    A Cross-Platform Memory Leak Detector
    UML Diagrams Using Graphviz Dot
    My Emacs Writing Setup
    Drawing Graphs using Dot and Graphviz
    SHFileOperation的用法
    latex中文模板
    C++ Design Pattern: What is a Design Pattern?
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3192179.html
Copyright © 2020-2023  润新知