使用静态指针来管理类内存?

发布于 2024-12-11 09:37:18 字数 741 浏览 0 评论 0原文

我在游戏中有一个星星类,我希望它们使用相同的纹理,所以我想出了这个代码...

sf::Texture* Star::starTexture = NULL;
unsigned int Star::refCount = 0;

Star::Star() : starSpeed(0), starScale(0), locX(0), locY(0)
{
    if (starTexture == NULL)
    {
        starTexture = new sf::Texture();
    }

    refCount++;
}

Star::~Star()
{
    refCount--;

    if (refCount == 0)
    {
        delete starTexture;
        starTexture = NULL;
    }
}

我正在使用这样的星星类...

for (int i = 0; i < STAR_COUNT; ++i)
{
    Star star;

    star.Initialize(/* blah blah */);

    starVector.push_back(star);
}

我是“高级 C++”的新手技术”,我担心这行不通。我需要定义一个复制构造函数吗?向量会扰乱我的引用计数吗?我也愿意接受有关更好方法的建议。我想我可以将纹理保留在类之外,并在初始化每个星星时传递引用,但我更喜欢将纹理保留在类内......

I have a class for stars in my game, I want them to use the same texture so I've come up with this code...

sf::Texture* Star::starTexture = NULL;
unsigned int Star::refCount = 0;

Star::Star() : starSpeed(0), starScale(0), locX(0), locY(0)
{
    if (starTexture == NULL)
    {
        starTexture = new sf::Texture();
    }

    refCount++;
}

Star::~Star()
{
    refCount--;

    if (refCount == 0)
    {
        delete starTexture;
        starTexture = NULL;
    }
}

I'm using the star class like this...

for (int i = 0; i < STAR_COUNT; ++i)
{
    Star star;

    star.Initialize(/* blah blah */);

    starVector.push_back(star);
}

I'm new to "advanced c++ techniques" and I'm worried this isn't going to work. Do I need to define a copy constructor? will the vector mess up my reference count? I'm open to suggestions for a better way to do this too. I guess I could keep the texture outside the class and pass a reference when I initialize each star but I perfer the texture staying inside the class...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌无敌 2024-12-18 09:37:18

是的,如果你没有为你的类显式定义复制构造函数复制赋值运算符,它就会变得混乱。

vector 这样的 STL 容器具有按值复制语义。当Star对象被复制到vector时,它内部的原始指针也被复制。因此,您现在有多个指针指向单个内存,这肯定会让您在最好的情况下走上未定义行为的快车道。

您应该做的是明确定义这些函数。手动执行该内存的深层复制并正确增加引用计数。

更好的方法是在类中保存一个 RAII 对象,例如 boost::shared_ptr 或 std::tr1::shared_ptr ,并让它处理资源管理(包括引用)自动为您计算东西)。那么您就不再需要显式定义这些函数了。

class Star
{
..
private:
  std::tr1::shared_ptr<sf::Texture> m_starTexture;
};

// link the smart pointer w/ resource
Star::Star(): m_starTexture(new Texture())
{
  ...  
}

这是通过语言功能保证的:

  1. 当复制对象时,将调用非静态成员对象的复制函数
  2. 当你的对象被删除时,非静态成员对象的析构函数被调用

在这种情况下,复制智能指针的函数将正确增加引用计数,而
它的析构函数将减少引用计数,如果引用计数等于 0,则释放资源。

Yes, it'll mess up if you don't explicitly define copy constructor and copy assignment operator for you class.

STL containers like vector have copy-by-value semantics. When Star object is copied into a vector, the raw pointer inside it is copied. So you now have multiple pointers pointing to a single memory, which definitely puts you on the fast track to undefined behavior, at best.

What you should do, is to define those functions explicitly. Manually perform the deep copy of that memory and increment your ref count properly.

A better way is to hold an RAII-object like boost::shared_ptr or std::tr1::shared_ptr inside your class and let it handle resource management(including ref-counting stuff) automatically for you. Then you don't need explicitly define those functions anymore.

class Star
{
..
private:
  std::tr1::shared_ptr<sf::Texture> m_starTexture;
};

// link the smart pointer w/ resource
Star::Star(): m_starTexture(new Texture())
{
  ...  
}

This is guaranteed to work by language features:

  1. When your object is copied, copying functions of non-static member objects are called.
  2. When your object is deleted, destructors of non-static member objects are called.

In this case, copying functions of smart pointer will correctly increment ref count while
destructor of it will decrement ref count, and deallocate the resource if ref count equals 0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文