C ++中的静态或内联有什么区别
What's the difference static or inline in C++
我是 C++ 的新手,我对 static
和 inline
感到困惑。我想要做的是定义一个全局计数器。我在下面的代码上对其进行了测试(它只是一个框架来说明这个想法)
// 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
声明和定义是理想的,因为变量真正定义一次,不需要进一步的链接器工作。
我是 C++ 的新手,我对 static
和 inline
感到困惑。我想要做的是定义一个全局计数器。我在下面的代码上对其进行了测试(它只是一个框架来说明这个想法)
// 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
声明和定义是理想的,因为变量真正定义一次,不需要进一步的链接器工作。