有 C++ 惰性指针吗?

Posted

技术标签:

【中文标题】有 C++ 惰性指针吗?【英文标题】:Is there C++ lazy pointer? 【发布时间】:2009-05-18 15:00:38 【问题描述】:

我需要一个类似shared_ptr 的对象,但是当我尝试访问它的成员时它会自动创建一个真实的对象。

例如,我有:

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.

是否有一些实现,或者我应该自己编写?

【问题讨论】:

【参考方案1】:

自己动手做起来很轻松。

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;

【讨论】:

将 child 包含为 auto_ptr 是有意义的 您甚至可以使用 boost::optional 代替子指针。使用 boost::optional 意味着您可以从它的堆栈分配中受益。然后不使用堆 此外,此自定义解决方案需要一个复制构造函数。 如何让 child 可变,这样 const 方法就不会返回 0? @ehemient:我同意 Thomas 的观点,应该将 child 声明为 mutable。这正是mutable 旨在解决的问题。我的意思是,如果你想要纯常量,那么这样的类无论如何都是一个糟糕的设计,在这种情况下,我什至认为它是不正确的!【参考方案2】:

使用boost::optional,你可以有这样的事情:

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

将构造 100 个lazy's 并将一个真正的some_big_stuff 分配给v[49]boost::optional 将不使用堆内存,但使用placement-new 在堆栈分配的缓冲区中创建对象。我会像这样围绕boost::optional 创建一个包装器:

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;
;

这现在使用boost::optional 来做事。它应该支持像这样的就地构造(op* 上的示例):

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

这不需要任何复制。但是,当前的 boost 手册不包括该赋值运算符重载。然而,消息来源确实如此。我不确定这是否只是手册中的一个缺陷,或者是否故意遗漏了它的文档。所以我会使用更安全的方式来使用T() 进行复制分配。

【讨论】:

vector&lt;LazyPtr&lt;Box&gt; &gt; v(100) 将使用 100*sizeof(Box),这可能没问题,但也许 OP 不想为未分配的 Box 使用内存。由于OP没有描述更多的要求,我们不知道...... 对,我不想在未分配的对象上浪费空间。【参考方案3】:

我从来没有听说过这样的事情,但话说回来,我从来没有听说过很多事情。 “惰性指针”如何将有用的数据放入底层类的实例中?

您确定 sparse matrix 不是您真正想要的吗?

【讨论】:

因为稀疏矩阵可以满足类似(尽管不相同)的需求。请注意,海报的示例显示了“惰性指针”的向量;这听起来很像一个稀疏矩阵。【参考方案4】:

据我所知,目前还没有这种事情的实现。不过创建一个并不难。

【讨论】:

以上是关于有 C++ 惰性指针吗?的主要内容,如果未能解决你的问题,请参考以下文章

c 和 c++ 中的指针之间有啥大的区别吗? [关闭]

C++类体系中this指针不能改变指向吗?

我可以直接从 C++ 中向量元素的指针获取索引吗?

我可以使用 C++ 中的指针访问二维数组的元素吗?

C++ 指针与 std::vector:对长变量有任何影响吗?

Go和C++的指针区别,gc后指针会变吗?