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

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

  1. 提示编译器认为在调用点替换函数体优于通常的函数调用机制。
  2. 即使省略了内联替换,也会遵循内联的其他规则(特别是 w.r.t 一个定义规则)。

通常,如果需要,任何主流编译器都会在调用点替换函数体,因此仅仅为 #1标记函数 inline实际上是不需要的。

进一步,当你声明一个函数为 static inline函数时,

函数上的 static关键字迫使 inline函数有一个内部链接(内联函数具有外部连接)这样一个函数的每个实例都被视为一个单独的函数(每个函数的地址不同) ,并且这些函数的每个实例都有它们自己的静态局部变量和字符串文字(内联函数只有这些函数的一个副本)的副本

因此,这样一个函数的行为就像任何其他的 static函数和关键字 inline没有重要性了,它变得多余。

因此,实际上标记一个函数 staticinline都没有任何用处。要么是 static(不太喜欢) ,要么是 inline(最喜欢) ,
那么,在函数 差不多吧上同时使用 staticinline是否无用呢?

109051 次浏览

Your analysis is correct, but doesn't necessarily imply uselessness. Even if most compilers do automatically inline functions (reason #1), it's best to declare inline just to describe intent.

Disregarding interaction with inline, static functions should be used sparingly. The static modifier at namespace scope was formerly deprecated in favor of unnamed namespaces (C++03 §D.2). For some obscure reason that I can't recall it was removed from deprecation in C++11 but you should seldom need it.

So, Practically marking a function static and inline both has no use at all. Either it should be static(not most preferred) or inline(most preferred),

There's no notion of preference. static implies that different functions with the same signature may exist in different .cpp files (translation units). inline without static means that it's OK for different translation units to define the same function with identical definitions.

What is preferred is to use an unnamed namespace instead of static:

namespace {
inline void better(); // give the function a unique name
}


static inline void worse(); // kludge the linker to allowing duplicates

If you talk about free functions (namespace scope), then your assumption is correct. static inline functions indeed don't have much value. So static inline is simply a static function, which automatically satisfies ODR and inline is redundant for ODR purpose.

However when we talk about member methods (class scope), the static inline function does have the value.
Once you declare a class method as inline, it's full body has to be visible to all translation units which includes that class.

Remember that static keyword has a different meaning when it comes for a class.
Edit: As you may know that static function inside a class doesn't have internal linkage, in other words a class cannot have different copies of its static method depending on the translation (.cpp) units.
But a free static function at namespace/global scope does have different copies per every translation unit.

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
}

Static and inline are orthogonal (independent). Static means the function should not be visible outside of the translation unit, inline is a hint to the compiler the programmer would like to have this function inlined. Those two are not related.

Using static inline makes sense when the inlined function is not used outside of the translation unit. By using it you can prevent a situation of accidental violation of ODR rule by naming another inlined function in another tranlation unit with the same name.

Example:

source1.cpp:

inline int Foo()
{
return 1;
}


int Bar1()
{
return Foo();
}

source2.cpp:

inline int Foo()
{
return 2;
}


int Bar2()
{
return Foo();
}

Without using static on Foo (or without using an anonymous namespace, which is preferred way by most C++ programmers), this example violates ODR and the results are undefined. You can test with Visual Studio the result of Bar1/Bar2 will depend on compiler settings - in Debug configuration both Bar1 and Bar2 will return the same value (inlining not used, one implementation selected randomly by the linker), in Release configuration each of them will return the intended value.

I may not be completely right about this, but as far as I know declaring a function static inline is the only way to make (or allow) the compiler to generate a machine code where the function really is not defined in the compiled code at all, and all you have is a direct substitution of the function call into a sequence of instructions, like it were just a regular procedure body, with no trace in the machine code of a procedure call relative to that function definition from the source code.

That is, only with static inline you can really substitute the use of a macro, inline by itself is not enough.

A simple Google search for "static inline" will show you compiler documentation pages that talk about it. I guess this should be enough to answer your question, and say, "no, it is not practically useless". Here is one example of a site discussing the use of inline, and specifically of static inline http://www.greenend.org.uk/rjk/tech/inline.html

I just read a man page for gcc and it specifically states the use of static inline with a compiler flag. In the case of the flag, it inlines the function and if it is also static and is inlined in every instance that it is called, then it gets rid of the function definition which will never be used in the created object file, thereby reducing the size of the generated code by that little bit.