Вы можете использовать умный указатель вашего собственного дизайна, который фиксирует его при первом разыменовании (конечно, перегружая операторы разыменования и косвенного обращения).
Это пример умного указателя, который создает экземпляр данного объекта при первом разыменовании (отложенная реализация). Та же идея, в основном:
template <typename T>
struct default_constructor_factory
{
T * operator ()() { return new T; }
};
template <typename T, typename F = default_constructor_factory<T> >
class lazy_ptr : boost::noncopyable
{
public:
typedef T element_type;
typedef T value_type;
typedef F factory_type;
typedef lazy_ptr<T,F> this_type;
lazy_ptr() : m_ptr(), m_factory() { }
lazy_ptr(F factory) : m_ptr(), m_factory(factory) { }
~lazy_ptr() { if (m_ptr != NULL) delete m_ptr; }
T & operator* () const
{
return *get();
}
T * operator-> () const
{
return get();
}
T * get() const
{
if (m_ptr == NULL)
m_ptr = m_factory();
return m_ptr;
}
void reset(T * p)
{
if (p != m_ptr)
{
if (m_ptr != NULL)
delete m_ptr;
m_ptr = p;
}
}
T * release()
{
T * p = m_ptr;
m_ptr = NULL;
return p;
}
// non-dereferencing accessors
T * peek() const
{
// may return NULL
return m_ptr;
}
bool dereferenced() const
{
return peek() != NULL;
}
// operator bool() const { return dereferenced(); }
// handle intrinsic conversion to testable bool using unspecified_bool technique
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return dereferenced() ? &this_type::m_ptr : NULL;
}
private:
// we must remain it's only owner!
mutable T * m_ptr;
// our factory generates the needed element on-demand
mutable factory_type m_factory;
};
// shared_lazy_ptr
//
// we act as a copyable lazy pointer
// essentially, we add reference counting to a single shared lazy pointer
//
template <typename T, typename F = default_constructor_factory<T> >
class shared_lazy_ptr
{
public:
typedef T element_type;
typedef T value_type;
typedef F factory_type;
typedef lazy_ptr<T,F> ptr_type;
typedef shared_lazy_ptr<T,F> this_type;
shared_lazy_ptr() : m_ptr(new ptr_type) { }
shared_lazy_ptr(F factory) : m_ptr(new ptr_type(factory)) { }
// copy ctor
shared_lazy_ptr(const this_type & rhs) : m_ptr(rhs.m_ptr), m_references(rhs.m_references) { }
// assignment
this_type & operator = (const this_type & rhs)
{
if (m_references.Reattach(rhs.m_references))
delete m_ptr;
m_ptr = rhs.m_ptr;
return *this;
}
~shared_lazy_ptr()
{
if (m_references.IsOnly())
delete m_ptr;
}
T & operator* () const
{
return *get();
}
T * operator-> () const
{
return get();
}
T * get() const
{
return m_ptr->get();
}
void reset(T * p)
{
if (p != get())
{
if (m_ptr != NULL)
delete m_ptr;
m_ptr = p;
}
}
// non-dereferencing accessors
T * peek() const
{
// may return NULL
return get()->peek();
}
bool dereferenced() const
{
return peek() != NULL;
}
// operator bool() const { return dereferenced(); }
// handle intrinsic conversion to testable bool using unspecified_bool technique
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return dereferenced() ? &this_type::m_ptr : NULL;
}
private:
lazy_ptr<T, F> * m_ptr; // shared *lazy* pointer to the actual object
ReferenceCount m_references; // shared reference count to our lazy pointer
};