2010-08-26 36 views
6

Điều gì về việc gọi shared_from_this cho các đối tượng được cấp phát stack? enable_shared_from_this trong danh sách lớp cơ sở là chỉ báo cho người dùng của lớp dẫn xuất để tạo ra nó chỉ trên heap (và chúng tôi chỉ hy vọng cho việc sử dụng lớp chính xác) hoặc chúng ta có thể có một số bảo vệ mạnh hơn chống lại các lỗi như vậy? Hoặc tôi không hiểu một số khoảnh khắc? đang

Ví dụ: enable_shared_from_this và các đối tượng trên stack

 
class C : public enable_shared_from_this<C> 
{ 
public: 
    shared_ptr<C> method() { shared_from_this(); } 
};

void func() { C c; shared_ptr<C> ptr = c.method(); // exception comming from shared_from_this() }

+1

Bạn hỏi chính xác điều gì? Bạn có muốn biết liệu có cách nào để ngăn chặn việc gọi 'shared_from_this()' trên các đối tượng được phân bổ không? –

Trả lời

10

Vì vậy, để bảo vệ chống lại vấn đề này, bạn có thể làm cho contstructors riêng tư và chỉ cung cấp chức năng tạo mà trở về shared_ptr - theo cách này đối tượng không thể được cấp phát trên stack, như thế này:

class C : public enable_shared_from_this<C> 
{ 
public: 
    static shared_ptr<C> create() { return shared_ptr<C>(new C()); } 
    shared_ptr<C> method() { shared_from_this(); } 

private: 
    C() {...} 

    // Make operator= and C(const C&) private unimplemented 
    // so the used cant do bad things like C c(* c_ptr); 
    C& operator=(const C &); 
    C(const C &); 
}; 


void func() 
{ 
    C c; // This doesnt compile 
    shared_ptr<C> ptr = c.method(); // So you can never get this 
} 

void altfunc() 
{ 
    shared_ptr<C> c_ptr = C::create(); 
    C & c_ref = *c; 
    shared_ptr<C> ptr = c_ref.method(); // OK 
} 

Nếu bạn thấy mình có nhu cầu cho anoperator = bạn có thể cung cấp một chức năng nhân bản bằng cách sử dụng thực hiện constructor sao chép tư nhân, một cái gì đó như thế này

// This goes in class C 
shared_ptr<C> C::clone() const 
{ 
    return shared_ptr<C>(new C(*this)); 
} 

// This is how you can use it 
shared_ptr<C> c2 = c1->clone(); 
+0

Tôi biết rằng bạn có thể vẫn phân bổ chúng trên stack nếu bạn sẵn sàng nhảy qua một số hoops để được cố ý ác .. nhưng IMHO này bảo vệ khỏi những sai lầm ngây thơ nhất. –

+0

Vì vậy, ban đầu chúng tôi sẽ thiết kế các lớp chỉ dành cho heap ... Cách tiếp cận này có được sử dụng rộng rãi không? – cybevnm

+0

Tại sao bạn cần vô hiệu hóa toán tử gán? Nó thường là tốt để gán cho/từ các đối tượng được tổ chức trong shared_ptr. Nó sẽ được xử lý giống như bất kỳ phép gán nào khác giữa hai đối tượng * hiện có * - số lượng tham chiếu sẽ không bị ảnh hưởng. Hai * đối tượng * khác nhau sẽ chỉ có cùng nội dung sau khi gán. – nobar

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