假设我有这个:
struct Base {
virtual void swap();
Expensive mem;
};
struct Left : Base {
void swap() override;
};
struct Right : Base {
void swap() override;
};
给出一个包含vector<shared_ptr<Base>> foo
和Left
对象的Right
。可以说元素13是Left
,现在我希望它是Right
。我可以做类似的事情:
foo[13] = make_shared<Right>();
但是现在让我们假设Expensive
的构建或复制非常昂贵,并且假设Left
和Right
不包含自己的成员,它们只是一种不同的处理方式操纵和解释mem
。有没有办法我可以强制或告诉元素13它现在是Right
而又不破坏那里的Left
?我是否可以使用enable_shared_from_this
或类似的方法将销毁和重建操作到我可以称之为foo[13].swap()
的地方,它将“变成” Right
?
答案 0 :(得分:2)
好吧,您可以考虑将Left
和Right
设为相同的类型。但是,如果您不能做到这一点,那么您仍然可以利用移动语义。假设Expensive
的价格便宜。然后您可以执行以下操作:
struct Base {
Base(Expensive mem) : mem(std::move(mem)) {}
virtual std::shared_ptr<Base> swap() = 0;
Expensive mem;
};
struct Left : Base {
Left(Expensive mem) : Base(std::move(mem)) {}
std::shared_ptr<Base> swap() override;
};
struct Right : Base {
Right(Expensive mem) : Base(std::move(mem)) {}
std::shared_ptr<Base> swap() override;
};
std::shared_ptr<Base> Left::swap() {
return std::make_shared<Right>(std::move(mem));
}
std::shared_ptr<Base> Right::swap() {
return std::make_shared<Left>(std::move(mem));
}
// ...
foo[13] = foo[13]->swap();
(请注意,在输入foo[13]
的主体之前,std::shared_ptr<Base>::operator=
所指向的原始对象不会被破坏,此时swap()
将完成并离开{{ 1}}处于可破坏状态,因此在我看来这段代码是定义明确的。)