懒惰地重新创建其资源的智能指针

Smart pointer that lazily recreates its resource

我有一个 ServiceProvider class,其中包含几个指向不同服务的指针,例如:

class ServiceProvider()
{
    Service3* GetService3();

public:
    void Process(Object* o);
    void Shrink();

private:
    TAutoSpawningPtr<Service1> service1;
    TAutoSpawningPtr<Service2> service2;

    Service3* service3;
}

请注意,TAutoSpawningPtr 是我正在寻找的理论上的智能指针 сlass,并且 service3 被声明为普通指针,以明确显示我需要的行为。 Process() 的正文:

void ServiceProvider::Process(Object* o)
{
    service1->Process(o);
    service2->Process(o);
    GetService3()->Process(o);
}

GetService3()的正文:

void ServiceProvider::GetService3()
{
    if(!service3)
    {
       service3 = new Service3();
    }

    return service3;
}

如您所见,正在延迟创建 Service3 的实例,直到需要时才存在。

Shrink() 方法被定期调用以删除所有内部服务。像这样:

void ServiceProvider::Shrink()
{
    service1.Release(); // delete its internal Service1 pointer if it exists.
    service2.Release(); // delete its internal Service2 pointer if it exists.

    if (service3)
    {
        // delete its internal Service3 pointer if it exists.
        delete service3;
        service3 = nullptr;
    }
}

我需要什么:我希望TAutoSpawningPtr<>成为一个智能指针class,自动一旦我使用重载 operator-> 取消引用指针,就会通过调用默认构造函数来创建其 class 实例。一旦调用 Release() 方法,就必须删除指针拥有的内部资源(当然,当我再次需要它时,必须重新创建它)。

为什么我需要这个?

  1. 自动控制对象presence/absence。
  2. 直接取消引用指针(如this->service3->Process(o))而不是间接取消引用时防止空指针GetService3()
  3. 在没有明确检查的情况下释放未使用的服务。

问题是:标准(或任何第三方)库是否有自动指针class可以满足我的需要?如果没有,请您给我一些代码示例来展示我需要的行为。谢谢。

这里最简单的解决方案是只调用一个函数来初始化这两个函数,如果它们未初始化或没有指向任何东西。

但如果您真的想要,您可以创建一个简单的代理指针 class 来为您完成这项工作。例如

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

class Something {
public:
    Something() {
        cout << __PRETTY_FUNCTION__ << endl;
    }
    void do_something() {
        cout << __PRETTY_FUNCTION__ << endl;
    }
};

template <typename Type,
          template <typename...> class Ptr = std::unique_ptr>
class AutoAllocatingPtr {
public:
    Type* operator->() {
        if (!this->ptr) {
            this->ptr = Ptr<Type>{new Type{}};
        }
        return this->ptr.get();
    }

    void release() {
        this->ptr.reset();
    }

private:
    Ptr<Type> ptr;
};

int main() {
    // default unique ownership with std::unique_ptr
    auto ptr = AutoAllocatingPtr<Something>{};
    ptr->do_something();
    ptr.release();
    ptr->do_something();

    // if you want shared ownership
    auto s_ptr = AutoAllocatingPtr<Something, std::shared_ptr>{};
    s_ptr->do_something();
    s_ptr.release();
    s_ptr->do_something();
}

注意 请注意最后的代码以及如何使用它来切换指针展示的所有权语义类型。