C ++初始化静态堆栈

时间:2009-04-23 03:25:31

标签: c++ collections static initialization

我对初始化静态集合有一些疑问。这是我编码的一个例子似乎有效:

#include <stack>
#include <iostream>

using namespace std;

class A
{
    private:
        static stack<int> numbers;

        static stack<int> initializeNumbers();

    public:
        A();
};

A::A() { cout << numbers.top() << endl; }

stack<int> A::initializeNumbers()
{
    stack<int> numbers;

    numbers.push(42);

    return numbers;
}

stack<int> A::numbers = initializeNumbers();

int main()
{
    A a;
}

现在,这是我想要完成的最佳方式吗?出于某种原因,当我在我的实际代码中尝试这个完全相同的方案时,调用 top()会打印出乱码。这有什么理由吗?

如果我的例子没问题,也许我会求助于发布我的真实代码。


这是真正的代码:

Light.h

#ifndef LIGHT_H_
#define LIGHT_H_

#include <stack>

#include "Vector4.h"

class Light
{
    private:
        static stack<GLenum> availableLights;

        static stack<GLenum> initializeAvailableLights();

    public:
        GLenum lightID;
        Vector4 ambient, diffuse, specular, position, spotDirection;
        GLfloat constantAttenuation, linearAttenuation, quadraticAttenuation, spotExponent, spotCutoff;

        Light(  const Vector4& ambient = Vector4(0.0, 0.0, 0.0, 1.0),
                const Vector4& diffuse = Vector4(1.0, 1.0, 1.0, 1.0),
                const Vector4& specular = Vector4(1.0, 1.0, 1.0, 1.0),
                const Vector4& position = Vector4(0.0, 0.0, 1.0, 0.0),
                const Vector4& spotDirection = Vector4(0.0, 0.0, -1.0, 0.0),
                GLfloat constantAttenuation = 1.0,
                GLfloat linearAttenuation = 0.0,
                GLfloat quadraticAttenuation = 0.0,
                GLfloat spotExponent = 0.0,
                GLfloat spotCutoff = 180.0);

        ~Light();
};

#endif /*LIGHT_H_*/

Light.cpp

#include <stdexcept>    // runtime_error
#include <iostream>

using namespace std;

#include "Light.h"

Light::Light(   const Vector4& ambient,
                const Vector4& diffuse,
                const Vector4& specular,
                const Vector4& position,
                const Vector4& spotDirection,
                GLfloat constantAttenuation,
                GLfloat linearAttenuation,
                GLfloat quadraticAttenuation,
                GLfloat spotExponent,
                GLfloat spotCutoff) :

                ambient(ambient),
                diffuse(diffuse),
                specular(specular),
                position(position),
                spotDirection(spotDirection),
                constantAttenuation(constantAttenuation),
                linearAttenuation(linearAttenuation),
                quadraticAttenuation(quadraticAttenuation),
                spotExponent(spotExponent),
                spotCutoff(spotCutoff)
{
    // This prints gibberish.
    cout << availableLights.size() << endl;

    // The error is indeed thrown.
    if(availableLights.empty())
        throw runtime_error("The are no more available light identifiers.");
    else
    {
        lightID = availableLights.top();

        availableLights.pop();
    }
}

Light::~Light() { availableLights.push(this -> lightID); }

stack<GLenum> Light::initializeAvailableLights()
{
    stack<GLenum> availableLights;

    availableLights.push(GL_LIGHT7);
    availableLights.push(GL_LIGHT6);
    availableLights.push(GL_LIGHT5);
    availableLights.push(GL_LIGHT4);
    availableLights.push(GL_LIGHT3);
    availableLights.push(GL_LIGHT2);
    availableLights.push(GL_LIGHT1);
    availableLights.push(GL_LIGHT0);

    return availableLights;
}

stack<GLenum> Light::availableLights = initializeAvailableLights();

由于我无法使用堆栈的代码工作,我现在选择了这个:

Light.h

#ifndef LIGHT_H_
#define LIGHT_H_

#include <stack>

#include "Vector4.h"

class Light
{
    private:
        static const unsigned int LIGHTS = 9;
        static bool availableLights[];
        static GLenum lights[];

        static GLenum getAvailableLight();

    public:
        GLenum lightID;
        Vector4 ambient, diffuse, specular, position, spotDirection;
        GLfloat constantAttenuation, linearAttenuation, quadraticAttenuation, spotExponent, spotCutoff;

        Light(  const Vector4& ambient = Vector4(0.0, 0.0, 0.0, 1.0),
                const Vector4& diffuse = Vector4(1.0, 1.0, 1.0, 1.0),
                const Vector4& specular = Vector4(1.0, 1.0, 1.0, 1.0),
                const Vector4& position = Vector4(0.0, 0.0, 1.0, 0.0),
                const Vector4& spotDirection = Vector4(0.0, 0.0, -1.0, 0.0),
                GLfloat constantAttenuation = 1.0,
                GLfloat linearAttenuation = 0.0,
                GLfloat quadraticAttenuation = 0.0,
                GLfloat spotExponent = 0.0,
                GLfloat spotCutoff = 180.0);

        ~Light();
};

#endif /*LIGHT_H_*/

Light.cpp

#include <stdexcept>    // runtime_error

#include "Light.h"

Light::Light(   const Vector4& ambient,
                const Vector4& diffuse,
                const Vector4& specular,
                const Vector4& position,
                const Vector4& spotDirection,
                GLfloat constantAttenuation,
                GLfloat linearAttenuation,
                GLfloat quadraticAttenuation,
                GLfloat spotExponent,
                GLfloat spotCutoff) :

                ambient(ambient),
                diffuse(diffuse),
                specular(specular),
                position(position),
                spotDirection(spotDirection),
                constantAttenuation(constantAttenuation),
                linearAttenuation(linearAttenuation),
                quadraticAttenuation(quadraticAttenuation),
                spotExponent(spotExponent),
                spotCutoff(spotCutoff)
{
    lightID = getAvailableLight();
}

Light::~Light()
{
    for(unsigned int i = 0; i < LIGHTS; i++)
        if(lights[i] == lightID)
            availableLights[i] = true;
}

bool Light::availableLights[] = {true, true, true, true, true, true, true, true};
GLenum Light::lights[] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7};

GLenum Light::getAvailableLight()
{
    for(unsigned int i = 0; i < LIGHTS; i++)
        if(availableLights[i])
        {
            availableLights[i] = false;

            return lights[i];
        }

    throw runtime_error("The are no more available light identifiers.");
}

任何人都可以在堆栈代码中发现错误,或者改进我的仓促编码解决方法吗?

4 个答案:

答案 0 :(得分:1)

我认为代码甚至不会编译(从A::开始缺少initializeNumbers())。

我建议您发布真实的代码。

但是,为什么不只是在第一个构造函数调用上初始化堆栈(如果你当然在多线程环境中运行,则使用线程保护)。

这似乎是一种更清洁的方式,类似于(未经测试):

#include <stack>
#include <iostream>
using namespace std;
class A {
    private:
        static boolean isInited = false;
        static stack<int> numbers;
    public:
        A();
};

A::A() {
    if (!isInited) {
        numbers.push(42);
        isInited = true;
    }
    cout << numbers.top() << endl; }

int main() {
    A a;
}

答案 1 :(得分:1)

这是一种方法:

#include <stack>

class C {
    static std::stack< C* > c_stack;
    static std::stack< C* > getCStack();
};

std::stack< C* > C::c_stack = C::getCStack();

std::stack< C* > C::getCStack() {
    std::stack< C* >* c_stack = new std::stack< C* >();
    c_stack->push( new C());
    return *c_stack;
}

答案 2 :(得分:0)

这绝对是有原因的。这种方法通常有两个问题。第一个问题是静态初始化器在main方法在C ++中启动之前运行。这意味着initializeNumbers将在程序中的任何其他内容之前运行。在这个有限的样本中,这不是什么大问题。

第二个问题是C ++没有为订购提供任何保证。这意味着如果您有多个静态初始化变量,编译器可以按照它喜欢的顺序自由地初始化它们。因此,如果您在其他初始化程序中依赖于一个静态变量,那么您将遇到错误(并且很容易创建一个微妙的依赖项)。

在这里为复杂的静态值进行某种形式的延迟初始化可能会好得多。

答案 3 :(得分:0)

想知道这些方面的内容是否会对你有所帮助。我仍然更喜欢Pax的建议,它更简单,但这应该避免你的“初始化”担忧。

class NumStack : public stack<int>
{
public:
   NumStack(){
      push(42);
   }
};

class A
{
    private:
        static NumStack numbers;

    public:
        A();
};

//in cpp file, do as usual for static members
NumStack A::Numbers;

如果继承使你有问题(它应该,它不是很漂亮),只需将堆栈聚合到NumStack中。这需要对代码中数字的使用进行一些更改,但是:

class NumStack
{
public:
   NumStack(){
      obj.push(42);
   }
   stack<int> obj;
};