header 中定义的静态类方法中的 C++ 静态变量

标签 c++ class static

// 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/

相关文章:

c++ - 更改描述函数行为的位置会导致错误?

python - 有没有办法在创建类(不是实例)时调用(静态)方法?

javascript - 我如何静态声明一个 Javascript 对象实例(又名 "associative array"),其属性名称(又名键)包含破折号?

c# - 如何在 C++ 中声明类的静态实例?

C++静态结构体成员变量效率

c++ - 使用反向冒泡排序对数据结构数组进行字母排序

c++ - 计算边界框的顶点

c++ - 输出到 stdout/cout/etc 的进程间同步

vba - 在 VBA 中链接类

c# - 可以创建不区分大小写的字符串类吗?