考虑这个简单的类:
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:现在正确转发“参数”。
答案 0 :(得分:5)
在C ++中尽可能避免在构造新状态之前销毁旧状态,因为无法提供强大的异常保证:“操作成功,或者抛出异常而不更改任何内容”。因此,标准库没有这样的(我甚至不能命名添加它的框架)。
天真和错误的复制构造者有时会这样做 如果你故意想要获得这种行为,那就没有比为自己编码更好的了 但是,要确定这是你想要的,并为后代记录。
你的ResourceManager
似乎主要是做你想做的事
尽管如此,请确保方法名称/类名明确地调出您的非标准行为(ResourceManager
和replace
都不够具体)。
答案 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"));