2009-04-25 16 views
5

Bạn nghĩ sao? Điều này có đúng hay có rò rỉ bộ nhớ không?QList và shared_ptr

Nguồn:

#include <QList.h> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) { m_data = value; } 
    ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; } 
    operator int() const { return m_data; } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    QList<boost::shared_ptr<A> > list; 
    list.append(boost::shared_ptr<A>(new A(6))); 
    std::cout << int(*(list.at(0))) << std::endl; 
    return 0; 
} 

Output:

6 
destroying A(6) 
+2

Là một sidenote: không sử dụng 'QList ' trong đó 'sizeof (T)> sizeof (void *)' (và 'sizeof (shared_ptr ) == 2 * sizof (void *)', thường), vì trong trường hợp đó, 'QList' sẽ sao chép' '' 'các phần tử vào danh sách (trái ngược với việc giữ nó theo giá trị). Sử dụng 'QVector' hoặc' std :: vector' để thay thế. –

Trả lời

1

Có vẻ như chính xác. Shared_ptr của Boost là một con trỏ đếm tham chiếu. Việc đếm tham chiếu có thể đòi lại bộ nhớ nếu không có tham chiếu vòng tròn giữa các đối tượng. Trong trường hợp của bạn, các đối tượng của lớp A không tham chiếu đến bất kỳ đối tượng nào khác. Vì vậy, bạn có thể sử dụng shared_ptr mà không phải lo lắng. Ngoài ra, ngữ nghĩa quyền sở hữu cho phép shared_ptrs được sử dụng trong các container STL (và Qt).

1

Rất khó để đề nghị bất cứ điều gì mà không biết lý do tại sao danh sách các shared_ptr s của A đối tượng tồn tại ở nơi đầu tiên.

Hãy xem ownership semantics con trỏ thông minh. Có thể giúp bạn.

Một số thứ khác mà có thể được cải thiện:

1. danh sách Sử dụng initializer trong ctor như:

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) : m_data (value) {} 
// .... 

2.int _tmain(int argc, _TCHAR* argv[]) không phải là một chữ ký tiêu chuẩn;

Sử dụng

int main(int argc, char* argv[]) 

hoặc chỉ:

int main() 
+0

Tôi không chắc chắn ý của bạn là gì với điểm đầu tiên của bạn. Tôi nên sử dụng danh sách khởi tạo ở đâu? '_tmain' là mặc định khi sử dụng thuật sĩ Visual Studio nhưng cảm ơn cho gợi ý đó! – WolfgangA

+1

_tmain (int argc, _TCHAR * argv []) là chữ ký hợp lệ trên VC++ :). Đó là một phương pháp chính có đối số nhiều byte hoặc unicode, tùy thuộc vào công tắc trong VS. Ngoài ra còn có một int wmain (int argc, wchar_t * argv []). – Skurmedel

+0

Việc triển khai có thể cung cấp N chữ ký khác nhau của chính. Ngôn ngữ chuẩn chỉ định nghĩa hai (tôi đã đề cập ở trên). – dirkgently

1

Mã này trông hoàn toàn tốt đẹp.

Nếu bạn đang tìm kiếm lời khuyên, bạn có thể cung cấp thêm thông tin về mục đích sử dụng shared_ptr với QList, có thể có cách "Qt" để thực hiện việc này mà không cần kéo những khẩu súng lớn như shared_ptr.

+1

không hoàn toàn chính xác. bạn có thể sử dụng cây quyền sở hữu đối tượng của Qt như bố cục, chuyển QList làm chủ sở hữu của từng đối tượng được chèn vào nó. đó là một kỹ thuật rất hữu ích khi làm việc với Qt. đọc thêm về nó ở đây: http://doc.trolltech.com/4.5/objecttrees.html –

+0

@daniel Đó không phải là một tùy chọn ở đây, vì cha mẹ và trẻ em phải là lớp con QObject để làm việc. QList không phải là QObject vì vậy nó không phải là đi ngay cả khi A được thừa kế từ QObject. –

1

Nếu bạn không sử dụng con trỏ thông minh, bạn phải tự xóa các phần tử danh sách.

Nguồn:

#include <QList.h> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) { m_data = value; } 
    ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; } 
    operator int() const { return m_data; } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    QList<A *> list; 
    list.append(new A(6)); 
    std::cout << int(*(list.at(0))) << std::endl; 
    return 0; 
} 

Output:

6 

Không tốt.

+0

Sau đó, chỉ cần loại bỏ toán tử "mới" và đối tượng A sẽ được giải mã khi QList là. –