2010-05-04 30 views
5

Ai có thể giải thích cách giải phóng bộ nhớ của một biến thành viên tĩnh? Theo sự hiểu biết của tôi, nó chỉ có thể được giải phóng nếu tất cả các trường hợp của lớp bị phá hủy. Tôi là một chút bất lực vào thời điểm này ...Làm thế nào để giải phóng biến thành viên tĩnh trong C++?

Một số luật để giải thích nó:

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

Trả lời

11

Từ âm thanh của nó, bạn thực sự không muốn một con trỏ nào cả. Trong thực tế, vì điều này đến từ một hàm nhà máy trong một thư viện C, nó không thực sự là một con trỏ C++ "hạng nhất". Ví dụ: bạn không thể an toàn delete nó.

Vấn đề thực sự (nếu có) là gọi SDL_FreeSurface trước khi chương trình thoát.

Điều này yêu cầu một lớp trình bao bọc đơn giản.

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; 

Khi chương trình khởi tạo, hàm tạo được gọi và tệp được đọc. Khi chương trình thoát, hàm hủy được gọi và đối tượng bị hủy.

12

Con trỏ chính nó sẽ được xung quanh cho đến khi chương trình tắt. Tuy nhiên, những gì nó trỏ đến là trò chơi công bằng. Bạn có thể giải phóng nó bất cứ lúc nào.

Nếu bạn đang lo lắng về là rò rỉ bộ nhớ, sau đó bạn có một vài lựa chọn mà tôi nhìn thấy:

  1. Chỉ cần để cho nó bị rò rỉ. Tất cả bộ nhớ từ chương trình sẽ được phát hành khi nó tắt. Tuy nhiên, nếu bạn cần nhiều hơn chỉ là bộ nhớ được giải phóng (như bạn muốn một destructor để chạy), thì đó không phải là một ý tưởng tốt.

  2. Có biến thành viên tĩnh theo dõi số lượng phiên bản của lớp đã được tạo. Giải phóng bộ nhớ khi nó đạt đến 0 và tái phân bổ nó nếu nó vượt quá 0 lần nữa.

  3. Có chức năng thuộc loại nào đó chạy khi chương trình tắt và lo lắng về việc giải phóng bộ nhớ.

  4. Nếu bạn có thể, hãy tạo nó để nó không còn là con trỏ nữa. Nếu nó không phải là một con trỏ, bạn không phải lo lắng về nó.

  5. Sử dụng smart pointer hoặc auto_ptr. Bằng cách đó, khi con trỏ bị phá hủy, bộ nhớ sẽ được xử lý.

Cá nhân, tôi khuyên 4 nếu bạn có thể và 5 nếu bạn không thể, nhưng bạn có một số tùy chọn.

+0

Đã xóa câu trả lời của tôi, câu trả lời tương tự với câu trả lời của bạn nhưng không hoàn toàn giống với câu trả lời của bạn. – Nate

+0

Ý tưởng của tôi là làm như bạn mô tả trong 2. nhưng tôi nghĩ rằng có thể là một cách tốt hơn. Con trỏ thông minh là gì? Chưa từng nghe điều đó trước đây. Âm thanh như bộ sưu tập rác .. – user299831

+0

Con trỏ thông minh là đối tượng chứa con trỏ, cho phép bạn sử dụng nó như thể nó là con trỏ và giải phóng bộ nhớ đó cho con trỏ khi nó bị phá hủy (thường được thực hiện bằng cách đếm tham chiếu để xem liệu có là bất kỳ tham chiếu nào còn lại cho con trỏ). Nó tương tự như thu gom rác ở chỗ nó quản lý bộ nhớ cho bạn, nhưng đó là một khái niệm riêng biệt. Tôi đã thêm một liên kết để triển khai tăng cường. Có rất nhiều thông tin trực tuyến trên chúng - bao gồm cả tại wikipedia. Ngoài ra, nếu bạn chỉ cần tìm kiếm con trỏ thông minh tại đây tại SO, bạn sẽ nhận được một số câu hỏi liên quan đến chúng. –

3

Biến thành viên tĩnh trong trường hợp này là con trỏ. Bạn không thể tự nó, nhưng bạn có thể giải phóng những gì nó trỏ tới:

SDL_FreeSurface(ball_image); 

Sau đó bạn có thể muốn đặt ball_image-0, để ghi lại thực tế là bạn không còn có một hình ảnh.

nó chỉ có thể được trả tự do nếu tất cả các thể hiện của lớp bị phá hủy

Nếu bởi "lớp" bạn có nghĩa là ball, sau đó không. Thành viên tĩnh của ball tiếp tục tồn tại bất kể số lượng phiên bản ball có. Cách duy nhất một thành viên tĩnh có thể bị phá hủy trước khi thoát khỏi chương trình là nếu bạn thực hiện một số điều (thực thi phụ thuộc) như dỡ bỏ dll chứa lớp đó. Nhưng trong trường hợp này thành viên tĩnh chỉ là một con trỏ, vì vậy (1) phá hủy nó sẽ phá hủy con trỏ, chứ không phải con trỏ, và (2) không cần phá hủy con trỏ, nó không chiếm các tài nguyên quan trọng.

1

Nếu bạn phải có thành viên tĩnh trỏ đến bộ nhớ phân bổ heap, tôi sẽ làm cho một thành viên trở thành một con trỏ thông minh.

1

Thành viên tĩnh tồn tại hoàn toàn độc lập với tất cả các phiên bản của lớp mà nó là thành viên của. Bạn có thể xóa con trỏ tại bất kỳ điểm nào trong chương trình. Cho dù điều này có ý nghĩa ngữ nghĩa, tất nhiên là một vấn đề khác.

1

Tôi đồng ý với câu trả lời của Jonathan M Davis, nhưng một tùy chọn khác mà bạn có thể xem xét là kéo hình ảnh và tài nguyên khác ra khỏi "đối tượng tên miền" của bạn và vào lớp ResourceManager hoặc thứ gì đó dọc theo các dòng đó.

Trình quản lý tài nguyên có thể là tĩnh hoặc dựa trên cá thể và sẽ cung cấp logic để tải và xóa tài nguyên, cần thiết cho phần còn lại của ứng dụng của chúng tôi.

Các lớp cần tài nguyên chỉ có thể chứa tham chiếu hoặc con trỏ tới trình quản lý tài nguyên toàn cầu và yêu cầu tài nguyên từ người quản lý thay vì tự quản lý chúng.

0

Biến thành viên tĩnh không cần xóa. Nếu bạn có một trong một lớp học, là bởi vì bạn muốn sử dụng nó bất cứ lúc nào trong suốt toàn bộ cuộc đời của chương trình. Khi chương trình kết thúc, Hệ điều hành sẽ xác nhận lại toàn bộ bộ nhớ được gán cho nó, bao gồm bất kỳ không gian bộ nhớ chưa xóa nào.

Tất nhiên, nếu bạn nhấn mạnh việc xóa nó, bạn có thể tạo một phương thức thành viên tĩnh đặc biệt để thực hiện nó và gọi phương thức tại một điểm mong muốn trong chương trình. Nhưng tôi không muốn giới thiệu nó cho bất kỳ ai, bởi vì nó vi phạm tính toàn vẹn ngữ nghĩa của các biến thành viên tĩnh, tăng độ phức tạp và khả năng gây rắc rối khi chương trình phát triển.

0

Làm việc với static variable nơi bộ nhớ được cấp động, tốt hơn là hãy đi theo số smart_pointer hoặc phương pháp xóa bộ nhớ theo cách thủ công.

Xoá ký ức của varibles tĩnh trong destructor sẽ không làm việc đối với trường hợp dưới đây: Các thành viên Như tĩnh tồn tại như members of the clas s chứ không phải là một instance in each object of the class. Vì vậy, nếu ai đó truy cập một biến tĩnh bằng cách sử dụng :: và cấp phát bộ nhớ động, destructor sẽ không xuất hiện trong ảnh và bộ nhớ sẽ không bị xóa, vì không có đối tượng nào được tạo.

Các vấn đề liên quan