代码之家  ›  专栏  ›  技术社区  ›  Remember Monica

方法的静态函数等价性

  •  -1
  • Remember Monica  · 技术社区  · 8 年前

    有时,我希望在一个头文件中有一个函数(包含在多个不同的翻译单元中),而不要求编译器将其内联(例如在一个只包含头的库中)。这样做很容易,只需声明函数 static 例如:

       struct somedata { ... }
    
       static somefunc (somedata *self) { ... }
    

    这允许编译器决定是否内联函数,同时仍然允许在多个翻译单元中对函数进行多个定义,因为它没有外部链接。还允许我用 somedata 结构是用其他翻译单位创建的,因为类型是兼容的。

    我的问题是,如何使用类和方法来实现这一点?例如,以这个头文件为例,使用类和方法(而不是函数和显式对象指针)实际上是相同的事情:

       struct someclass {
          void method ();
       }
    
       void someclass::method () { ... }
    

    显然,我不能用 static someclass::method 因为这完全是另一回事。

    我也不能将它放到匿名名称空间中,因为这样我会变得不同 struct someclass 不同翻译单位的类型,即我不能使用 someclass * 因为它们是不同的(和不兼容的)类型。

    我可以宣布所有这些方法 inline 这是可行的,但会产生不希望的效果,好吧,即使在没有任何意义的情况下,要求编译器内联它们。

    我是否漏掉了一些明显的东西,或者C++没有等价的东西吗? 静止的 对于方法?正如我所见(希望是错误的),我唯一的选择是要么将所有这些方法移动到一个单独的翻译单元中,要么将它们全部标记为内联-似乎没有与C样式内部链接等效的方法。

    更新: 我认为这个问题过早地以重复的形式结束了。假设重复的问题是,将函数标记为inline是否总是inline。这个问题是关于如何避免ODR规则作为普通函数的静态关键字,或者解释这是不能在C++中完成的,这两个问题都没有被另一个问题回答,它只是告诉ASKER不要担心它。在我的问题中,inline只是作为一个可能(但不好)的解决方案提出来的。

    更新2: 多次提到inline不是函数inline的请求,或者C标准只使用inline来绕过ODR规则,不要求编译器内联函数。

    这两种说法显然是不真实的。例如,仔细阅读gcc文档或llvm源代码可以发现广泛使用的编译器确实考虑了 内联 作为内联函数的请求。我还引用了C++ 03,在(7.1.2.2)中表示:

    […]内联说明符向实现表明,在调用点对函数体的内联替换优先于常规函数调用机制。[…]

    所以现有编译器和C++标准(我只检查1488 822003)显然不同意“内联只影响ODR”的重复请求。

    这种错误的看法似乎很普遍,如图所示: https://blog.tartanllama.xyz/inline-hints/ 有人通过查看实际的gcc/llvm源代码来调查此声明,发现两个编译器都将inline视为实际的inline请求。

    但是,请记住,我的问题是如何获得 静止的 对于C++中的成员函数,或者可选地得到一个更明确的声明,C++只对成员函数没有这个特性,只针对普通函数。的属性

    char *reserve (int bytes)
    {
      if (left <= bytes)
        flush ();
    
      if (left <= bytes)
        throw std::runtime_error ("bulkbuf allocation overflow");
    
      return cur;
    }
    

    //inline
    int f(int i)
    {   
      return i < 0 ? 0 : f(i-1) + 1;
    } 
    
    int main(int argc, char *[])
    {   
      return f(5) + f(argc);
    } 
    

    g++ -Os -S -o - test.C main

        movl    %edi, %ecx
        movl    $5, %edi
        call    f(int)
        movl    %eax, %edx
        movl    %ecx, %edi
        call    f(int)
        addl    %edx, %eax
        ret
    

            xorl    %eax, %eax
    .L3:
            cmpl    %eax, %edi
            js      .L2
            incl    %eax
            jmp     .L3
    .L2:
            addl    $6, %eax
            ret
    

    f

    Do c++11-compatible compilers always ignore inline hints?

    2 回复  |  直到 8 年前
        1
  •  2
  •   n. m. could be an AI    8 年前

    static inline

    // in several translation units
    static void foo_static() { 
       static int bar; // one copy per translation unit
    }
    
    // in several translation units
    inline void foo_inline() { 
       static int bar; // one copy in the entire program
    }
    

    &foo_static &foo_inline

    // in several translation units
    template <nullptr_t=nullptr>
    void foo_template() { 
       static int bar; // one copy in the entire program
    }
    
        2
  •  1
  •   Pete Becker    8 年前

    inline

    static