C++ 构造函数中的静态变量,是否有任何缺点或副作用?

C++ 构造函数中的静态变量,是否有任何缺点或副作用?,c++,constructor,initialization,static-variables,C++,Constructor,Initialization,Static Variables,我想做的是:每当类的实例要在程序中使用时,运行一些必备代码。此代码将检查需求等,并且只能运行一次 我发现这可以通过在构造函数中使用另一个对象作为静态变量来实现。下面是一个更好的例子: class Prerequisites { public: Prerequisites() { std::cout << "checking requirements of C, "; std::cout <<

我想做的是:每当类的实例要在程序中使用时,运行一些必备代码。此代码将检查需求等,并且只能运行一次

我发现这可以通过在构造函数中使用另一个对象作为静态变量来实现。下面是一个更好的例子:

class Prerequisites
{
     public:
         Prerequisites() {
              std::cout << "checking requirements of C, ";
              std::cout << "registering C in dictionary, etc." << std::endl;
         }
};


class C
{
    public:
         C() {
             static Prerequisites prerequisites;
             std::cout << "normal initialization of C object" << std::endl;
         }
};
类的先决条件
{
公众:
先决条件(){

std::cout这不是线程安全的,因为如果两个线程第一次尝试同时构造C,前提条件可能会被初始化两次

如果您对此没有意见,那么您可能可以这样做,尽管在作用域构造函数系统中玩游戏的可发现性为零(即,一旦您忘记了“诀窍”或其他人试图阅读您的代码,他们就会对发生了什么感到困惑)

是否有任何缺点或副作用,或者我遗漏了什么?或者可能有更好的解决方案?欢迎提供任何建议

显式调用静态方法可能更清晰(尽管更详细)

class Prerequisites
{
    static bool checkedOnce;    
public:
    static void checkOnce() {
        if (checkedOnce)
        {
            //already checked: don't check again
            return;
        }
        //else check them now
        checkedOnce = true;
        std::cout << "checking requirements of C, ";
        std::cout << "registering C in dictionary, etc." << std::endl;
    }
};

bool Prerequisites::checkedOnce = false;

class C
{
public:
    C() {
        Prerequisites::checkOnce();
        std::cout << "normal initialization of C object" << std::endl;
    }
};
类的先决条件
{
静态布尔校验;
公众:
静态void checkOnce(){
如果(检查)
{
//已检查:不再检查
返回;
}
//否则现在就检查一下
checkedOnce=true;

std::cout您至少应该在Premissions类中使用互斥锁和静态标志来保护Premissions对象的多次初始化。这样,您的代码将成为线程安全的。

我认为您应该重新考虑您的设计,而不是将任何prereq作为构造函数的参数。这会使依赖关系更加复杂为您的类的用户设置ar。@Anders K:这不是关于类用户的选择,而是关于测试运行时环境。更具体地说,我想检查C类将使用的可用OpenGL扩展。每当所需的扩展不可用时,程序将只打印错误消息并失败退出。我要做的是意思是一个用户(程序员)在使用你的类。更清楚的是,如果构造函数需要知道可用的opengl扩展,然后在幕后默默地进行操作。@Anders K:我知道你的意思,但事实并非如此。类用户(程序员)不知道C类可能需要什么,因为它是实现细节。另一方面,C类知道它需要什么,但由于OpenGL设计,这只能在运行时检查。是的,很明显,我想在你想隐藏时显示,就我个人而言,当我使用其他人的类时,我喜欢轻量的这并不是因为它们更易于重用,而是每个人都有自己的可重用性。线程安全性在这里不是问题,但感谢您的建议。顺便说一句,我听说C++0x将使静态变量的初始化成为线程安全的。您可能是对的,这一点更清晰。但是在checkOnce()中将
checkedOnce
boolean定义为静态又如何呢?不太冗长,但仍应清晰(?)C++0x中的原子性。@doc--我建议使用更详细的方法,因为它更清晰/更明确/使用更少的魔法。您能提供一个关于C++0x中静态局部变量原子性的引用/参考吗?我在stackoverflow上读到了下面的链接@doc,但编写代码时至少要注意线程(并不是明显的线程冷漠)通常会产生更干净、更快、更好、更具弹性的代码。@doc的意思是不要编写特别依赖于在单线程环境中运行的代码-例如“技巧”这里提到过。@Qix为什么不呢?在大多数情况下,单线程代码更干净,更不容易出错。如果您决定保证线程安全,那么代码的用户希望它是真正的线程安全。这使事情变得复杂,因为您必须处理互斥锁、锁、竞速条件、原子性,而且还有更多地方可以产生错误(在处理线程时,它们可能非常微妙且难以调试).@doc我从来没有说过保证线程安全。我是说不要因为你认为它总是单线程的就走捷径。我从来没有说过你需要使用互斥锁和锁等等。值得注意的是,使用任何兼容的C++11编译器都应该是线程安全的,因为神奇的静态是如何工作的。