代码之家  ›  专栏  ›  技术社区  ›  Robert Gould

如果内联是可选的,为什么删除“内联”会导致链接器错误?

  •  20
  • Robert Gould  · 技术社区  · 16 年前

    //Class.h
    class MyClass
    {
       void inline foo()
       {}
    };
    

    下一个更改为(不会链接):

    //Class.h
    class MyClass
    {
       void inline foo();
    };
    
    //Class.cpp
    void MyClass::foo()
    {}
    

    然后(会很好地工作):

    //Class.h
    class MyClass
    {
       void foo();
    };
    
    //Class.cpp
    void MyClass::foo()
    {}
    

    4 回复  |  直到 2 年前
        1
  •  38
  •   Johannes Schaub - litb    16 年前

    在所使用的每个翻译单位中定义。接下来是可怕的细节。第一 3.2/3 :

    每个程序应包含该程序中使用的每个非内联函数或对象的一个定义;无需诊断。定义可以显式出现在程序中,也可以在标准或用户定义的库中找到,或者(在适当的情况下)隐式定义(见12.1、12.4和12.8)。

    7.1.2/4 :

    但是,如果在类定义中定义函数,则隐式声明为 inline external 相同 entity

    3.5/5 :

    3.5/4 :

    具有命名空间范围的名称具有外部链接,如果它是命名类(子句9)的[…]的名称,或者是在typedef声明中定义的未命名类的名称,其中该类具有用于链接的typedef名称。

    typedef struct { [...] } the_name;
    

    从现在起,您对 同一实体 在您的程序中,ODR的另一件事恰好限制了您。 3.2/5

    我现在删掉了一些不重要的东西。以上是关于内联函数需要记住的两个重要内容。如果你多次定义一个外部内联函数,但确实以不同的方式定义了它,或者如果你定义了它并且其中使用的名称解析为不同的实体,那么你就是在做未定义的行为。

    函数必须在使用它的每个TU中定义的规则很容易记住。这也是很容易记住的。但是,关于名字解析的事情呢?这里举个例子。考虑一个静态函数 assert_it :

    static void assert_it() { [...] }
    

    现在,既然 static 不同实体 这意味着你 允许使用 assert_it


    以下是相同的事情:

    struct A { void f() { } };
    struct A { inline void f(); }; void A::f() { } // same TU!
    

    f

    struct A { void f(); }; void A::f() { } // evil!
    

    现在,如果你把 内联 关于宣言 f (以及

    内联 在C和C++中,仅用作内联替换提示。由于静态在任何时候都会创建一个不同的实体(因为内部链接), 内联

        2
  •  10
  •   Community Mohan Dere    8 年前

    该方法是否实际内联由编译器自行决定。然而,内联关键字的存在也会影响方法的链接。

    litb

        3
  •  6
  •   jrharshath    16 年前

    需要注意的是:当方法内联声明时,它的定义必须与其声明一起。

        4
  •  2
  •   Void - Othman    16 年前

    关于harath.jr的答案,如果一个方法的定义有“inline”关键字,并且该定义在同一个标头中可用,则不需要内联声明该方法, 也就是 :

    class foo
    {
      void bar();
    };
    
    inline void foo::bar()
    {
      ...
    }
    

    这对于根据构建是否为“”来有条件地内联方法非常有用 调试 “就像这样:

    // Header - foo.h
    
    class foo
    {
      void bar();  // Conditionally inlined.
    };
    
    #ifndef FOO_DEBUG
    # include "foo.inl"
    #endif
    

    // Inline Functions/Methods - foo.inl
    #ifndef FOO_DEBUG
    # define FOO_INLINE inline
    #else
    # define FOO_INLINE
    #endif
    
    FOO_INLINE void foo::bar()
    {
      ...
    }
    

    // Implementation file - foo.cpp
    #ifdef FOO_DEBUG
    # include "foo.inl"
    #endif
    
    ...