如何在C++中释放静态成员变量?

发布于 2024-08-31 00:26:15 字数 278 浏览 6 评论 0原文

有人可以解释如何释放静态成员变量的内存吗?根据我的理解,只有当该类的所有实例都被销毁时,它才能被释放。在这一点上我有点无助......

一些代码来解释它:

class ball
{
    private:
    static SDL_Surface *ball_image;
};
//FIXME: how to free static Variable?
SDL_Surface* ball::ball_image = SDL_LoadBMP("ball.bmp");

Can anybody explain how to free memory of a static member Variable? In my understanding it can only be freed if all the instances of the class are destroyed. I am a little bit helpless at this point...

Some Code to explain it:

class ball
{
    private:
    static SDL_Surface *ball_image;
};
//FIXME: how to free static Variable?
SDL_Surface* ball::ball_image = SDL_LoadBMP("ball.bmp");

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

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

发布评论

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

评论(8

治碍 2024-09-07 00:26:15

指针本身将一直存在,直到程序关闭。然而,它所指向的是公平游戏。您可以随时释放它。

如果您担心的是内存泄漏,那么我看到您有几个选择:

  1. 就让它泄漏吧。程序关闭时,所有内存都将被释放。但是,如果您需要的不仅仅是释放内存(就像您希望运行析构函数),那么这不是一个好主意。

  2. 有一个静态成员变量,用于跟踪已创建的类的实例数量。当内存达到零时释放内存,如果再次高于 0 则重新分配内存。

  3. 有一个在程序关闭时运行的某种函数,并让它担心释放内存。

  4. 如果可以的话,让它不再是一个指针。如果它不是指针,则不必担心。

  5. 使用智能指针auto_ptr。这样,当指针本身被销毁时,内存将被处理。

就我个人而言,如果可以的话我建议使用 4,如果不能的话建议使用 5,但是你有多种选择。

The pointer itself will be around until the program shuts down. However, what it points to is fair game. You can free that at any time.

If what you're worried about is memory leaks, then you have a few options that I see:

  1. Just let it leak. All the memory from the program will be released when it shuts down. However, if you need more than just the memory being freed (like you want a destructor to run), then that's not such a good idea.

  2. Have a static member variable which keeps track of how many instances of the class have been created. Free the memory when it reaches zero and reallocate it if it goes above 0 again.

  3. Have a function of some kind which runs when the program is shutting down and have it worry about freeing the memory.

  4. If you can, make it so that it's not a pointer anymore. If it's not a pointer, you don't have to worry about it.

  5. Use a smart pointer or auto_ptr. That way, when the pointer itself is destroyed, the memory will be taken care of.

Personally, I'd advise 4 if you can and 5 if you can't, but you have several options.

初见终念 2024-09-07 00:26:15

从它的声音来看,你根本不需要一个指针。事实上,由于它来自 C 库中的工厂函数,因此它并不是真正的“一流”C++ 指针。例如,您无法安全地删除它。

真正的问题(如果有的话)是在程序退出之前调用 SDL_FreeSurface

这需要一个简单的包装类。

struct smart_sdl_surface {
    SDL_Surface *handle;

    explicit smart_sdl_surface( char const *name )
        : handle( SDL_LoadBMP( name ) ) {}
    ~smart_sdl_surface()
        { SDL_FreeSurface( handle ); }
};

class ball
{
    private:
    static smart_sdl_surface ball_image_wrapper;
    static SDL_Surface *& ball_image; // reference to the ptr inside wrapper
};
smart_sdl_surface ball::ball_image_wrapper( "ball.bmp" );
SDL_Surface *&ball::ball_image = ball::ball_image_wrapper.handle;

当程序初始化时,构造函数被调用并读取文件。当程序退出时,析构函数被调用,对象被销毁。

From the sound of it, you don't really want a pointer at all. In fact, since this is coming from a factory function in a C library, it isn't really a "first-class" C++ pointer. For example, you can't safely delete it.

The real problem (if there is one) is to call SDL_FreeSurface on it before the program exits.

This requires a simple wrapper class.

struct smart_sdl_surface {
    SDL_Surface *handle;

    explicit smart_sdl_surface( char const *name )
        : handle( SDL_LoadBMP( name ) ) {}
    ~smart_sdl_surface()
        { SDL_FreeSurface( handle ); }
};

class ball
{
    private:
    static smart_sdl_surface ball_image_wrapper;
    static SDL_Surface *& ball_image; // reference to the ptr inside wrapper
};
smart_sdl_surface ball::ball_image_wrapper( "ball.bmp" );
SDL_Surface *&ball::ball_image = ball::ball_image_wrapper.handle;

When the program initializes, the constructor is called and the file is read. When the program exits, the destructor is called and the object is destroyed.

初吻给了烟 2024-09-07 00:26:15

本例中的静态成员变量是一个指针。您无法释放它,但可以释放它指向的内容:

SDL_FreeSurface(ball_image);

然后您可能希望将 ball_image 设置为 0,以记录您不再拥有图像的事实。

只有当该类的所有实例都被销毁时,它才能被释放

如果“类”指的是,那么不行。无论有多少个 Ball 实例,ball 的静态成员都会继续存在。在程序退出之前静态成员可能被销毁的唯一方法是执行一些(依赖于实现的)操作,例如卸载包含该类的 dll。但在这种情况下,静态成员只是一个指针,因此(1)销毁它只会销毁指针,而不是指针对象,(2)无论如何都不需要销毁指针,它不会占用大量资源。

The static member variable in this case is a pointer. You can't free it, but you can free what it points to:

SDL_FreeSurface(ball_image);

You might then want to set ball_image to 0, to record the fact that you no longer have an image.

it can only be freed if all the instances of the class are destroyed

If by "the class" you mean ball, then no. Static members of ball continue to exist regardless of how many instances of ball there are. The only way a static member might be destroyed before program exit is if you do some (implementation-dependent) thing like unloading the dll which contains the class. But in this case the static member is just a pointer, so (1) destroying it will just destroy the pointer, not the pointee, and (2) there is no need to destroy a pointer anyway, it doesn't occupy significant resources.

枕花眠 2024-09-07 00:26:15

如果必须让静态成员指向堆分配的内存,我会将成员设为智能指针。

If you must have the static member pointing to heap-allocated memory, I would make a member a smart pointer.

像你 2024-09-07 00:26:15

静态成员完全独立于其所属类的所有实例而存在。您可以在程序中的任何位置删除指针。当然,这在语义上是否有意义是另一个问题。

A static member exists completely independently of all instances of the class it is a member of. You can delete the pointer at any point in the program. Whether this makes sense semantically, is another issue, of course.

我要还你自由 2024-09-07 00:26:15

我同意 Jonathan M Davis 的回答,但您可以考虑的另一个选择是将图像和其他资源从“域对象”中拉出并放入 ResourceManager 类中,或者类似的东西。

ResourceManager 可以是静态的,也可以是基于实例的,并且将提供应用程序其余部分所需的加载和删除资源的逻辑。

需要资源的类可以只持有全局资源管理器的引用或指针,并向管理器请求资源,而不是自己管理它们。

I agree with Jonathan M Davis' answer, but another option you could consider is pulling your images and other resources out of your "domain objects" and into a ResourceManager class, or something along those lines.

The ResourceManager could either be static, or instance-based, and would provide the logic to load and delete resources, needed by the rest of our application.

Classes needing resources could just hold a reference or a pointer to the global resource manager, and request resources from the manager, rather than managing them themselves.

无言温柔 2024-09-07 00:26:15

静态成员变量不需要删除。如果您在班级中有一个,是因为您想在程序的整个生命周期中随时使用它。程序完成后,操作系统将收回分配给它的总内存,包括任何未删除的内存空间。

当然,如果您坚持删除它,您可以创建一个特殊的静态成员方法来执行此操作,并在程序中的所需位置调用该方法。但我不会向任何人推荐它,因为它违反了静态成员变量的语义完整性,随着程序的增长,增加了复杂性和引起麻烦的可能性。

Static member variables don't need to be deleted. If you have one within a class, is because you want to use it at any time during the entire life of the programme. Once the programme finishes, the Operating System claims back the total memory assigned to it, including any undeleted memory space.

Of course, if you insist in deleting it, you can create a special static member method for doing it and invoke the method at a desired point in the programme. But I woudn't recommend it to anyone, because it violates the semantic integrity of the static member variables, increasing so the complexity and the likelihood for causing troubles as the programme grows.

春庭雪 2024-09-07 00:26:15

使用动态分配内存的静态变量,最好使用smart_pointer或手动清除内存的方法。

析构函数中清除静态变量的内存对于以下情况不起作用:
由于静态成员作为类的成员而不是作为类的每个对象中的实例存在。因此,如果有人使用 :: 访问静态变量并动态分配内存,则 析构函数 将不会出现,内存也不会被删除,因为没有创建对象。

Working with a static variable where the memory is dynamically allocated, it is better to go with smart_pointer or a method where memory is cleared manually.

Clearing the memory of static varibles in the destructor will not work for the below case:
As static members exist as members of the class rather than as an instance in each object of the class. So if someone access a static variable using :: and dynamically allocate memory, the destructor will not come in picture and the memory will not get deleted, as there is no object created.

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