C ++有一个像unique_ptr这样的智能指针,带有“构造前的破坏”语义吗?

时间:2014-05-01 12:49:04

标签: c++ smart-pointers unique-ptr resourcemanager resource-management

问题

考虑这个简单的类:

struct C {
   C(const char* name) : name(name) {
         cout << "constructing " << name  << endl;
   }

   ~C() {
       cout << "destructing " << name << endl;
   }

   string name;
};

我想有一个指向这个类的实例的指针,它经常被另一个实例替换。但是,我希望在创建新实例之前销毁当前实例。

错误的例子

如果我以正常方式使用unique_ptr,则不起作用:

unique_ptr<C> c( new C("the first one"));
c.reset(new C("the second one"));

(不受欢迎)输出:

  

构建第一个

     

构建第二个

     

破坏第一个

     

破坏第二个

丑陋的例子

可以如下实现期望的效果:

unique_ptr<C> c( new C("the first one"));
c.reset();  // explicitly destruct the first one first
c.reset(new C("the second one"));

输出:

  

构建第一个

     

破坏第一个

     

构建第二个

     

破坏第二个

尝试解决方案

这是我尝试使用此行为创建智能指针。 这样的智能指针是否已存在?

template<typename Resource>
class ResourceManager {
  public:
    ResourceManager() {}

    template<typename... Arguments>
    ResourceManager(Arguments&&... args) {
      replace<Arguments...>(std::forward<Arguments>(args)...);
    }

    template<typename... Arguments>    
    void replace(Arguments&&... args) {
      resource.reset();
      resource.reset(new Resource(std::forward<Arguments>(args)...));
    }

  private:
    unique_ptr<Resource> resource;
};

template<typename Resource, typename... Arguments>
ResourceManager<Resource> make_resource_manager(Arguments... args) {
        return ResourceManager<Resource>(args...);
}

int main() {
   //ResourceManager<C, const char*> r("first1");
   auto r = make_resource_manager<C>("first1");
   r.replace("second1");
}

输出:

  

构建第一个

     

破坏第一个

     

构建第二个

     

破坏第二个

编辑:将“参数...”模板移至功能级别。

编辑2:现在正确转发“参数”。

3 个答案:

答案 0 :(得分:5)

在C ++中尽可能避免在构造新状态之前销毁旧状态,因为无法提供强大的异常保证:“操作成功,或者抛出异常而不更改任何内容”。因此,标准库没有这样的(我甚至不能命名添加它的框架)。

天真和错误的复制构造者有时会这样做 如果你故意想要获得这种行为,那就没有比为自己编码更好的了 但是,要确定这是你想要的,并为后代记录。

你的ResourceManager似乎主要是做你想做的事 尽管如此,请确保方法名称/类名明确地调出您的非标准行为(ResourceManagerreplace都不够具体)。

答案 1 :(得分:2)

标准中没有类似的东西。我不确定为什么你想要那个特定的顺序,要么对象仍然存在,你可以重用它,否则你最终可能无法构造新的对象和一个空的智能指针。

答案 2 :(得分:2)

你可以使用C ++预处理器中不受欢迎的:

#define REPLACE_C(ptr,new_value) \
    do { \
        ptr.reset(); \
        ptr.reset(new_value); \
    while(false)

unique_ptr<C> c( new C("the first one"));
REPLACE_C(c, new C("the second one"));