2009-05-18 29 views
13

Tôi cần một đối tượng giống như shared_ptr, nhưng nó sẽ tự động tạo một đối tượng thực khi tôi cố gắng truy cập các thành viên của nó.Có con trỏ lười C++ không?

Ví dụ, tôi có:

class Box 
{ 
public: 
    unsigned int width; 
    unsigned int height; 
    Box(): width(50), height(100){} 
}; 

std::vector< lazy<Box> > boxes; 
boxes.resize(100); 

// at this point boxes contain no any real Box object. 
// But when I try to access box number 50, for example, 
// it will be created. 

std::cout << boxes[49].width; 

// now vector contains one real box and 99 lazy boxes. 

Có một số thực hiện, hay tôi nên viết của riêng tôi?

Trả lời

17

Đó là rất ít nỗ lực để cuộn của riêng bạn.

template<typename T> 
class lazy { 
public: 
    lazy() : child(0) {} 
    ~lazy() { delete child; } 
    T &operator*() { 
     if (!child) child = new T; 
     return *child; 
    } 
    // might dereference NULL pointer if unset... 
    // but if this is const, what else can be done? 
    const T &operator*() const { return *child; } 
    T *operator->() { return &**this; } 
    const T *operator->() const { return &**this; } 
private: 
    T *child; 
}; 

// ... 

cout << boxes[49]->width; 
+2

nó sẽ có ý nghĩa để chứa con như auto_ptr –

+0

Nhưng làm thế nào bạn sẽ khởi tạo hộp [49] -> chiều rộng để có một giá trị khởi tạo không tầm thường (tức là, không phải 0)? Bạn có thể muốn có một giao diện cho phép hàm tạo cho * (hộp [49]) nhận chỉ mục của nó làm đối số, để nó có thể phân biệt chính nó với các hộp khác. Điều đó có nghĩa là sử dụng một cái gì đó khác với std: vector, và đặt bạn vào miền của vectơ/ma trận thưa thớt. –

+2

Bạn thậm chí có thể sử dụng tăng :: tùy chọn thay vì con trỏ con. Sử dụng boost :: optional có nghĩa là bạn có lợi cho việc phân bổ stack của nó. Không có heap nào được sử dụng thì –

2

Tôi chưa bao giờ nghe nói về một điều như vậy, nhưng sau đó một lần nữa có rất nhiều điều tôi chưa bao giờ nghe nói đến. Làm thế nào để "con trỏ lười biếng" đưa dữ liệu hữu ích vào các trường hợp của lớp cơ bản?

Bạn có chắc chắn rằng sparse matrix không phải là những gì bạn thực sự đang tìm kiếm không?

+1

Tại sao bạn trỏ đến ma trận thưa thớt? –

+0

Vì ma trận thưa thớt lấp đầy một nhu cầu tương tự (mặc dù không giống nhau). Lưu ý rằng ví dụ của người đăng hiển thị một vectơ "con trỏ lười biếng"; điều này nghe có vẻ giống như một ma trận thưa thớt. –

0

Cho đến giờ tôi biết, hiện không có triển khai thực hiện loại điều này. Nó sẽ không khó để tạo ra một mặc dù.

10

Sử dụng boost::optional, bạn có thể có một điều như vậy:

// 100 lazy BigStuffs 
std::vector< boost::optional<BigStuff> > v(100); 
v[49] = some_big_stuff; 

sẽ xây dựng 100 của lười biếng và gán một thực some_big_stuff để v[49]. boost::optional sẽ không sử dụng bộ nhớ heap, nhưng sử dụng vị trí mới để tạo các đối tượng trong bộ đệm được phân bổ theo chồng. Tôi sẽ tạo ra một wrapper xung quanh boost::optional như thế này:

template<typename T> 
struct LazyPtr { 
    T& operator*() { if(!opt) opt = T(); return *opt; } 
    T const& operator*() const { return *opt; } 

    T* operator->() { if(!opt) opt = T(); return &*opt; } 
    T const* operator->() const { return &*opt; }  
private: 
    boost::optional<T> opt; 
}; 

này bây giờ sử dụng boost::optional để làm chất liệu. Nó phải hỗ trợ tại chỗ xây dựng như thế này (ví dụ trên op*):

T& operator*() { if(!opt) opt = boost::in_place(); return *opt; } 

Trong đó sẽ không yêu cầu bất kỳ bản sao-ing. Tuy nhiên, hướng dẫn tăng cường hiện tại không bao gồm quá tải của toán tử gán đó. Tuy nhiên, mã nguồn. Tôi không chắc liệu đây có phải chỉ là một khiếm khuyết trong sách hướng dẫn hay liệu tài liệu của nó có bị bỏ sót hay không. Vì vậy, tôi sẽ sử dụng cách an toàn hơn bằng cách sử dụng phân công bản sao bằng cách sử dụng T().

+2

'vectơ > v (100)' sẽ sử dụng 100 * sizeof (Hộp), có thể được nhưng có lẽ OP không muốn sử dụng bộ nhớ cho các Hộp không được cấp phát. Vì OP không mô tả thêm yêu cầu, chúng tôi không biết ... – ephemient

+0

Bạn nói đúng, đó là một điểm tốt :) –

+0

Phải, tôi không muốn lãng phí dung lượng cho các đối tượng không được phân bổ. –