应该从不使用静态内联函数吗?

时间:2012-06-04 06:02:53

标签: c++ static inline

使用inline关键字(第7.1.3 / 4节)有两个含义:

  1. 提示编译器,在通常的函数调用机制中,函数体的替换优于通常的函数调用机制。
  2. 即使省略内联替换,也会遵循内联的其他规则(尤其是w.r.t 一个定义规则)。
  3. 通常,如果需要,任何主流编译器都会在调用点替换函数体,因此不需要仅为inline标记函数#1

    进一步w.r.t #2,据我所知,当你将函数声明为static inline函数时,

    函数上的static关键字强制inline函数具有内部链接(内联函数具有外部链接)此类函数的每个实例都被视为单独的函数(每个函数的地址不同),这些函数的每个实例都有自己的静态局部变量和副本的副本。字符串文字(内联函数只有这些的一个副本)

    因此,这样的函数就像任何其他static函数一样,关键字inline不再重要,它变得多余。

    因此,实际标记函数staticinline两者都没有用。它应该是static不是最喜欢的)或inline最喜欢的),
    那么,在函数上使用staticinline几乎无用吗?

5 个答案:

答案 0 :(得分:47)

您的分析是正确的,但并不一定意味着无用。即使大多数编译器都自动执行内联函数(原因#1),最好只声明inline来描述意图。

应谨慎使用忽略与inlinestatic函数的交互。命名空间范围内的static修饰符以前不赞成使用未命名的命名空间(C ++03§D.2)。由于一些模糊的原因,我不记得它已从C ++ 11中的弃用中删除,但你很少需要它。

  

所以,实际上标记一个函数static和inline都没有用。它应该是静态的(不是最优选的)或内联的(最优选的),

没有偏好的概念。 static表示具有相同签名的不同函数可能存在于不同的.cpp文件(翻译单元)中。没有inline的{​​{1}}表示不同的翻译单元可以定义相同的定义相同的函数。

首选的是使用未命名的命名空间而不是static

static

答案 1 :(得分:21)

静态和内联是正交的(独立的)。静态意味着函数不应该在转换单元之外可见,内联是程序员想要内联此函数的编译器的提示。这两者无关。

在内联函数未在翻译单元之外使用时,使用static inline是有意义的。通过使用它,您可以通过在另一个具有相同名称的转换单元中命名另一个内联函数来防止意外违反ODR规则的情况。

示例:

source1.cpp:

inline int Foo()
{
  return 1;
}

int Bar1()
{
  return Foo();
}

source2.cpp:

inline int Foo()
{
  return 2;
}

int Bar2()
{
  return Foo();
}

在Foo上不使用静态(或者不使用匿名命名空间,这是大多数C ++程序员的首选方式),此示例违反ODR并且结果未定义。您可以使用Visual Studio进行测试,Bar1 / Bar2的结果将取决于编译器设置 - 在Debug配置中,Bar1和Bar2将返回相同的值(内联未使用,链接器随机选择一个实现),在Release配置中每个都是将返回预期值。

答案 2 :(得分:13)

我对此可能不完全正确,但据我所知,声明函数static inline是使编译器生成(或允许)生成机器代码的唯一方法,其中函数实际上未定义在所编译的代码中,你所拥有的只是将声明的函数直接替换为一系列指令,就像它只是一个常规的过程体,在相对于该函数定义的过程调用的机器代码中没有跟踪来自源代码。

也就是说,只有使用static inline才能真正替代宏的使用,inline本身是不够的。

简单的谷歌搜索“静态内联”将向您展示讨论它的编译器文档页面。我想这应该足以回答你的问题了,并说“不,它实际上没用”。以下是讨论inline使用情况的网站示例,特别是static inline http://www.greenend.org.uk/rjk/tech/inline.html

答案 3 :(得分:10)

如果您谈论免费功能(namespace范围),那么您的假设是正确的。 static inline函数确实没有多大价值。因此static inline只是一个static函数,它会自动满足ODR,inline对于ODR来说是多余的。

但是,当我们谈论成员方法(class范围)时,static inline函数确实具有该值。
class方法声明为inline后,必须对包含该class的所有翻译单元显示全文。

请注意,static关键字在class时具有不同的含义 修改:您可能知道static内的class函数没有内部链接,换句话说,一个类不能拥有其static的不同副本1}}方法取决于翻译(.cpp)单位static /全局范围内的免费namespace函数确实每个翻译单元都有不同的副本。

e.g。

// file.h
static void foo () {}
struct A {
  static void foo () {}
};

// file1.cpp
#include"file.h"
void x1 ()
{
  foo();  // different function exclusive to file1.cpp
  A::foo();  // same function
}

// file2.cpp
#include"file.h"
void x2 ()
{
  foo();  // different function exclusive to file2.cpp
  A::foo();  // same function
}

答案 4 :(得分:1)

我刚刚阅读了gcc的手册页,它特别指出静态内联使用编译器标志。在标志的情况下,它内联函数,如果它也是静态的,并且在调用它的每个实例中都是内联的,那么它将摆脱永远不会在创建的目标文件中使用的函数定义,从而减少生成的代码的大小。

相关问题