// SomeOtherClass.hpp
#pragma once
int someOtherCallMe();
class SomeOtherClass {
public:
static int callMe() {
static int _instance = 7;
++_instance;
return _instance;
}
};
// SomeOtherClass.cpp
#include "SomeOtherClass.hpp"
int
someOtherCallMe() {
return SomeOtherClass::callMe();
}
// main.cpp
#include "SomeOtherClass.hpp"
#include <iostream>
int
main() {
std::cout << SomeOtherClass::callMe();
std::cout << someOtherCallMe();
return 0;
}
我有三个文件:SomeOtherClass.hpp/cpp、main.cpp。这些文件生成两个二进制文件:共享库(SomeOtherClass.cpp)和可执行文件(main.cpp,与共享库链接)。
C++ 是否保证 static <any-type> _instance
将在程序执行期间成为单个变量(与定义了多少个二进制文件无关)?
注意
澄清情况。我在这种情况下看到的困惑是,一方面,SomeOtherClass::callMe
在程序中定义了两次,这是预期的(因为类静态成员函数实际上是一个具有内部链接的常规函数,如果它们是在适当的位置定义的,就像在这种情况下),这就是您可以从反汇编中看到的。由于我们在机器代码中有两个带有静态局部变量的函数。语言/标准如何限定他们的行为?
最佳答案
是的。静态将是单个值。许多其他东西没有明确定义或对标准来说是新的。 (如果它们是全局的,它们什么时候初始化?函数中的静态初始化代码是线程安全的吗?)但是,是的,你可以指望只有一个。
此处唯一的说明不在标准范围内,但如果您正在创建共享库(.so 或 .dll)则具有实际重要性:您不能静态(私下)将 C++ 类库链接到共享库。否则,如果您在两个不同的共享库中执行此操作,则会生成两个拷贝。 (此注释适用于库的所有内容,而不仅仅是静态变量。如果您这样做,那么所有内容都会重复。)
编辑:在许多平台(例如 Linux 和 Windows)上,这可用于有目的地“隐藏”您的静态变量。如果您不让您的函数/类在 dll/so 外部可访问(使用 declspec 或可见性属性),那么您可以确保您的 dll/so 拥有整个类的自己的拷贝。这种技术可以帮助减少库之间不必要的交互。但是,在您的情况下,听起来您真的只想要一个,如果您的类在所有库中都具有适当的可见性(仅在一个库中可见,并且其他库链接到该库),情况就是如此。
再次编辑引用标准
如果一个具有外部链接的函数在一个翻译单元中被声明为内联,那么它应该在它出现的所有翻译单元中被声明为内联;无需诊断。具有外部链接的内联函数在所有翻译单元中应具有相同的地址。 外部内联函数中的静态局部变量始终引用同一对象。
7.1.2.4,C++14
关于 header 中定义的静态类方法中的 C++ 静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35631714/