【问题标题】:C++ static member variable scopeC++ 静态成员变量作用域
【发布时间】:2012-07-04 13:25:02
【问题描述】:

标题基本上说明了一切,我想知道 c++ 类的静态成员何时初始化以及何时超出范围。

我需要这个来解决以下问题。我有许多类 Foo 的对象,每个对象都需要访问由另一个类 Bar 封装的资源。同步不是问题,所以我希望所有对象共享同一个 Bar 实例。

我正在使用一个简单的托管指针进行引用计数。

我可以执行以下操作吗:

class Foo {
private:
    static managed_pointer<Bar> staticBar;
public:
    Foo() {
        if(!staticBar)
            staticBar = new Bar;
    }
    /*
     * use staticBar in various non-static member functions
     */
};

managed_pointer<Bar> Foo::staticBar = NULL;

managed_pointer staticBar 应该在 Bar 对象超出范围后立即删除它 - 但是什么时候会发生这种情况? Foo 的最后一个实例何时被破坏?在应用程序退出?

感谢您的建议!

【问题讨论】:

  • 哎呀,感谢您纠正错字。
  • 当您简单地删除最后一个实例或当您的程序存在时,Foo 的最后一个实例被破坏。无论类的实例有多少,类的静态成员都会存在。

标签: c++ scope static-members


【解决方案1】:

statics 和全局变量在程序启动之前初始化(在调用 main 之前,程序实际上在此之前启动)并在 main 退出后超出范围。

异常 - 局部静态(在函数内声明的静态变量)和未使用的模板类 staticmembers。

与实例数无关。

【讨论】:

  • 本地静态变量在程序启动前没有初始化。
  • 好的,谢谢。 “与实例数量无关”是什么意思? Foo 类的实例?
  • 是的,不管有多少 Foo 实例,它们都会共享 Bar。
  • @Gabi 和未使用的静态成员(如果类是模板)。
  • @LeSnip3R:是的,当然,这是我的意图,否则我可以让Bar 成为非静态成员,让Foos ctor 和 dtor 负责分配/删除Bar .
【解决方案2】:

该标准没有指定精确的初始化顺序,它是特定于实现的。它们将在程序开始时被实例化并在结束时被释放。

你必须非常小心你正在做的事情,因为如果你有一些其他依赖这个对象存在的静态对象,那就是 UB。不知道它们将以什么顺序被初始化。

您可能会查看 boost::call_once 之类的东西以确保它被初始化一次,但我不会依赖于静态初始化的顺序。

据我所知,你的代码可以工作,但我之前一直被静态初始化问题所困扰,所以我想警告你。

编辑:同样在您的代码中,当 managed_ptr 超出范围(程序结束)时,它将自动删除分配的内存。但是您不应该在 Bar 的析构函数中做任何不重要的事情,因为您可能会通过调用其他释放的实例甚至已删除的代码来触发 UB(就像我曾经在删除动态库时发生的那样)。基本上你是在一个雷区,所以要小心。

【讨论】:

  • 我不会在 Foo 中拥有任何其他 statics,但感谢您的警告,另一个细节值得牢记。编辑:也谢谢你的第二个警告,我会小心的。
  • 我的意思是,您的 程序 中的其他静态对象。如果稍后您决定创建另一个对象,例如 ReBar,它也是静态的,并且您认为“嘿,我可以调用 Bar::Something,因为它是静态的”,您应该小心。
【解决方案3】:

从您的问题中跳出的第一件事是常见的误解,即 scopelifetime 是等价的概念。他们不是。在某些情况下,与局部变量一样,lifetime 绑定到特定的 context,但情况并非总是如此。

一个类静态成员变量有类作用域(在程序中任何地方都可以访问)和静态生命周期,这意味着它将以相对于同一翻译单元中的其他静态变量的顺序进行初始化,并且相对于其他翻译单元中的其他静态变量以未定义的顺序进行初始化,before main(警告:无需执行初始化在 main 中的第一个语句之前,但保证在变量的第一个 odr-use 之前)。

【讨论】:

  • 类静态成员变量具有 class 范围:它仅在类中查找名称的上下文中可见。它具有静态生命周期和外部绑定(人们偶尔会将第三个概念与您提到的两个混淆)。不过,您已经提到了要点:生命周期和范围是正交的概念。 (至少在一定程度上。种情况下范围决定了生命周期。)
猜你喜欢
  • 2012-04-30
  • 1970-01-01
  • 2013-06-08
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多