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

时间:2017-06-28 08:45:15

标签: c++ pointers smart-pointers object-lifetime

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

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<>成为智能指针类,自动通过在取消引用后调用默认的construcror来创建其类实例指针使用重载operator->。一旦调用Release()方法,必须删除由指针引起的内部资源(当然,当我再次需要它时,必须重新创建它)。

我为什么需要这个?

  1. 自动控制对象的存在/不存在。
  2. 在直接取消指针(如this->service3->Process(o))而非间接GetService3()时阻止nullptrs。
  3. 在没有明确检查的情况下发布未使用的服务。
  4. 问题是:标准(或任何第三方)库是否具有满足我需求的自动指针类?如果没有,你会不会给我带来一些显示我需要的行为的代码示例。感谢。

1 个答案:

答案 0 :(得分:5)

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

但是如果你真的想要,你可以创建一个简单的代理指针类来为你做这件事。例如

#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();
}

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