将静态变量声明为函数/成员函数是一个坏习惯吗? [英] Is a bad practice to declare static variables into functions/member functions?

查看:109
本文介绍了将静态变量声明为函数/成员函数是一个坏习惯吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,一个同事向我展示了一个这样的代码:

Recently a fellow worker showed to me a code like this:

void SomeClass::function()
{
    static bool init = false;

    if (!init)
    {
        // hundreds of lines of ugly code
    }

    init = true;
}



他想检查 SomeClass 初始化为每个 Someclass 实例执行一段代码,但事实是,只有一个实例 SomeClass 将在程序的所有生命周期中存在。

He wants to check if SomeClass is initialized in order to execute some piece of code once per Someclass instance but the fact is that only one instance of SomeClass will exist in all the lifetime of the program.

他的问题是关于 init 静态变量,关于它的初始化。我已经回答了初始化发生一次,所以在第一次调用和 true 的值将是 false 其寿命。回答之后,我补充说,这种使用静态变量是不好的做法,但我不能解释为什么。

His question were about the init static variable, about when it's initialized. I've answered that the initialization occurs once, so the value will be false at first call and true the rest of its lifetime. After answering I've added that such use of static variables is bad practice but I haven't been able to explain why.

我一直在想的原因far的行为如下:

The reasons that I've been thinking so far are the following:


  • static bool init $ c> SomeClass :: function 可以通过非静态成员变量实现。

  • 无法检查 static bool init 值,因为它的可见性限制为 void SomeClass :: function()
  • 静态变量不是 ,因为它们定义了全局状态而不是对象状态。

  • The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.
  • Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.
  • The static variables aren't OOPish because they define a global state instead of a object state.

这个原因看起来很差,不开放,不是很具体的,所以我要求更多的理由来解释为什么在函数和成员函数空间中使用静态变量一个坏习惯。

This reasons looks poor, unclever and not very concrete to me so I'm asking for more reasons to explain why the use of static variables in function and member-function space are a bad practice.

谢谢!

推荐答案

罕见的发生,至少,在良好的质量代码,因为狭窄的情况下它是适当的。这基本上是一个全局状态的即时初始化(提供一些全局功能)。其典型示例是具有随机数生成器函数,其在对其的第一调用时对生成器进行种子。另一个典型的用法是返回单例的实例的函数,在第一次调用时初始化。但是其他用例的例子是很少和很远的。

This is certainly a rare occurrence, at least, in good quality code, because of the narrow case for which it's appropriate. What this basically does is a just-in-time initialization of a global state (to deliver some global functionality). A typical example of this is having a random number generator function that seeds the generator at the first call to it. Another typical use of this is a function that returns the instance of a singleton, initialized on the first call. But other use-case examples are few and far between.

一般来说,全局状态是不可取的,并且包含自足状态的对象是首选的模块化等)。但是如果你需要全局状态(有时你需要),你必须以某种方式实现它。如果你需要任何类型的非平凡全局状态,那么你应该可以使用单例类,并且提供该应用程序范围的单个实例的首选方法之一是通过一个函数来传递一个引用到一个本地静态实例初始化在第一次调用。如果全局状态需要更微不足道,那么使用本地static bool标志的方案肯定是一种可接受的方式。换句话说,我认为使用这种方法没有根本问题,但如果出现这样的代码,我自然会质疑它的动机(需要一个全局状态)。

In general terms, global state is not desirable, and having objects that contain self-sufficient states is preferred (for modularity, etc.). But if you need global state (and sometimes you do), you have to implement it somehow. If you need any kind of non-trivial global state, then you should probably go with a singleton class, and one of the preferred ways to deliver that application-wide single instance is through a function that delivers a reference to a local static instance initialized on the first call. If the global state needed is a bit more trivial, then doing the scheme with the local static bool flag is certainly an acceptable way to do it. In other words, I see no fundamental problem with employing that method, but I would naturally question its motivations (requiring a global state) if presented with such code.

与全局数据一样,多线程会导致像这样的简单实现的一些问题。全局状态的朴素介绍永远不会是线程安全的,这种情况也不例外,你必须采取措施来解决这个具体问题。这是全局状态不可取的原因的一部分。

As is always the case for global data, multi-threading will cause some problems with a simplistic implementation like this one. Naive introductions of global state are never going to be inherently thread-safe, and this case is no exception, you'd have to take measures to address that specific problem. And that is part of the reasons why global states are not desirable.


可以实现static bool init into SomeClass :: function的行为具有非静态成员变量。

The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.

如果有一个替代方法来实现相同的行为,对技术问题(如线程安全)。但在这种情况下,所需的行为是可疑的事情,更多的是实现细节,并且替代实现的存在不改变。

If there is an alternative to achieve the same behavior, then the two alternatives have to be judged on the technical issues (like thread-safety). But in this case, the required behavior is the questionable thing, more so than the implementation details, and the existence of alternative implementations doesn't change that.

其次,我没有看到如何通过基于非静态数据成员的任何东西替换全局状态的即时初始化一个静态数据成员)。即使你可以,这将是浪费的(要求每个对象存储一个一次一个程序执行的东西),并且仅仅这一点,不会使它成为一个更好的选择。

Second, I don't see how you can replace a just-in-time initialization of a global state by anything that is based on a non-static data member (a static data member, maybe). And even if you can, it would be wasteful (require per-object storage for a one-time-per-program-execution thing), and on that ground alone, wouldn't make it a better alternative.


SomeClass中的其他函数无法检查静态bool init值,因为它的可见性局限于void SomeClass :: function()scope。

Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.

我通常把它放在Pro列中(如在Pro / Con中)。这是一件好事。这是信息隐藏或封装。如果你可以隐藏不应该是别人关心的事情,那么伟大!但是如果有其他函数需要知道全局状态已经被初始化或者没有,那么你可能需要更多的单线类的行。

I would generally put that in the "Pro" column (as in Pro/Con). This is a good thing. This is information hiding or encapsulation. If you can hide away things that shouldn't be a concern to others, then great! But if there are other functions that would need to know that the global state has already been initialized or not, then you probably need something more along the lines of a singleton class.


静态变量不是OOPish,因为它们定义了全局状态而不是对象状态。

The static variables aren't OOPish because they define a global state instead of a object state.

OOPish还是不,谁在乎?但是,全球国家是这里的关注。不是那么多使用本地静态变量来实现其初始化。全球国家,特别是可变的全球国家,总体上是坏的,不应该被滥用。它们阻碍模块化(如果它们依赖于全局状态,模块不太自给自足),它们引入多线程关注,因为它们是固有的共享数据,它们使任何使用它们的功能是不可重入的(非纯的),它们进行调试困难等等。列表继续。但大多数这些问题不是如何实现它。另一方面,使用局部静态变量是一个很好的方法来解决static-initialization-order-fiasco,所以,它们是有益的,一个较少的问题,当引入一个(良好对齐的)全局状态到您的代码中。

OOPish or not, who cares? But yes, the global state is the concern here. Not so much the use of a local static variable to implement its initialization. Global states, especially mutable global states, are bad in general and should never be abused. They hinder modularity (modules are less self-sufficient if they rely on global states), they introduce multi-threading concerns since they are inherently shared data, they make any function that use them non-reentrant (non-pure), they make debugging difficult, etc... the list goes on. But most of these issues are not tied to how you implement it. On the other hand, using a local static variable is a good way to solve the static-initialization-order-fiasco, so, they are good for that reason, one less problem to worry about when introducing a (well-justified) global state into your code.

这篇关于将静态变量声明为函数/成员函数是一个坏习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆