假设我有这个:
struct Base {
virtual void swap();
Expensive mem;
};
struct Left : Base {
void swap() override;
};
struct Right : Base {
void swap() override;
};
给定一个包含Left
和Right
对象的vector<shared_ptr<Base>> foo
。假设元素13是Left
,现在我希望它是Right
。我可以做一些类似的事情:
foo[13] = make_shared<Right>();
但现在我们假设Expensive
的构建或复制成本非常高,并且假设Left
和Right
不包含自己的成员,它们只是操纵和解释mem
的不同方式。有没有一种方法可以让我投射或告诉元素13,它现在是一个Right
,而不破坏那里的Left
?我可以使用enable_shared_from_this
或类似的方法来处理破坏和重建,我可以称之为foo[13].swap()
,它会"变成"Right
吗?
好吧,您可以考虑将Left
和Right
设为同一类型。但是如果你不能做到这一点,那么你仍然可以利用移动语义。假设CCD_ 17是可廉价移动的。然后你可以做这样的事情:
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()
将完成并使mem
处于可破坏状态,所以在我看来,这个代码将是明确定义的(。