我需要一个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.
Run Code Online (Sandbox Code Playgroud)
是否有一些实现,或者我应该自己编写?
eph*_*ent 18
滚动你自己的努力很少.
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;
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 10
使用boost::optional,你可以有这样的事情:
// 100 lazy BigStuffs
std::vector< boost::optional<BigStuff> > v(100);
v[49] = some_big_stuff;
Run Code Online (Sandbox Code Playgroud)
将建设100级懒惰的,并分配一个真实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;
};
Run Code Online (Sandbox Code Playgroud)
这现在boost::optional用于做东西.它应该像这样支持就地构造(示例op*):
T& operator*() { if(!opt) opt = boost::in_place(); return *opt; }
Run Code Online (Sandbox Code Playgroud)
这不需要任何复制.但是,当前的boost-manual不包括赋值运算符重载.然而,消息来源确实如此.我不确定这只是手册中的缺陷还是故意遗漏其文档.所以我会使用更安全的方式使用复制赋值T().