C ++中的静态或内联有什么区别

What's the difference static or inline in C++

我是 C++ 的新手,我对 staticinline 感到困惑。我想要做的是定义一个全局计数器。我在下面的代码上对其进行了测试(它只是一个框架来说明这个想法

// in main.cc
#include "T.h"

int main() {
  runFuncInT() ;
  cout << "# of trans is " << trans_cnt ;
  return 0;
}

// in T.h
static size_t trans_cnt = 0;

// in T.cc
runFuncInT() {
  for (size_t i=0; i<10; i++)
    trans_cnt += 1;
}

如果我使用描述性 inline,一切都完美,输出是 # of trans is 10。但是,如果我使用 static,编译器会抛出错误 multiple definition of trans_cnt

在 C++17 中,您应该在 header 中将变量声明为 inline:

inline size_t trans_cnt = 0;

来自 https://en.cppreference.com/w/cpp/language/inline:

since C++17: Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", that meaning was extended to variables.


在 C++17 之前,如果您在包含在多个翻译单元中的 header 文件中声明一个变量,您需要在 header 中将该变量声明为 extern 并在 .cc 之一中定义。例如:

// in T.h
extern size_t trans_cnt;

// in T.cc
size_t trans_cnt = 0; // T.h must have been included.

然而,或者,您可以使用在 header 中定义为 inline 的函数的函数静态变量作为单例,例如:

// in T.h
inline size_t& trans_cnt() {
    static size_t value = 0;
    return value;
}

对于具有 non-constexpr 构造函数的 classes,static 函数局部变量使用 std::call_once 初始化,这并不昂贵但不是免费的(并且,对于这个原因,我自己不用这个方法)。


另一种避免在别处定义该变量的方法是模板的静态数据成员,它必须在 header:

中定义和声明
// in T.h
template<class T, class Tag = void> struct Static { static T value; }; // Declaration.
template<class T, class Tag> T Static<T, Tag>::value{}; // Definition and initialization with empty initializer-list.
// refer to it as Static<size_t>::value; 
// E.g.:
int main() {
    size_t& trans_cnt = Static<size_t>::value;
    size_t& trans_cnt2 = Static<size_t, struct the_second_one>::value;
    size_t& trans_cnt3 = Static<size_t, struct the_third_one>::value;
}

相比之下,C++17 inline 变量和 static 具有 constexpr 构造函数的局部函数(包括所有 built-in 类型)使用与静态完全相同的机制class 模板的数据成员:每个翻译单元都包含一个变量副本,但是链接器和 run-time 链接器通过 vague linking.[=28= 选择一个供所有翻译单元使用]

在整个程序的一个翻译单元中用 extern 声明和定义是理想的,因为变量真正定义一次,不需要进一步的链接器工作。