构造函数依赖注入:unique_ptr + move vs shared_ptr

Constructor dependency injection: unique_ptr + move vs shared_ptr

假设我们有这样的东西:

struct Complex{
    Complex(Part1 p1, Part2 p2, Part3 p3)
}

Part1 p1; 
Part2 p2;
Part3 p3; 

但是传递副本是无效的,所以我们需要转向指针。问题是使用什么类型 — unique_ptrshared_ptr

乍一看,由于Complexp1, p2, p3的真正所有者,所以unique_ptr似乎更好;但是,由于无法复制,我们需要使用 std::move.

所以我的问题是——对于这种情况,什么是更好的方法,从 Part 中创建 unique_ptr,然后在 Complex 的构造函数中使用 move , 或者从头开始创建 shared_ptr 并改用 shared_ptr?

最好的解决方案是让 Part 类型的移动成本更低,然后将它们移入。但是,如果这不是一个选项,您将不得不求助于动态管理它们。

正如您所说,Complex 拥有这些部分,因此它应该接受它们作为 std::uniqe_ptr<Part> 并将这些指针移动到它自己中。移动 std::unique_ptr 非常便宜:它可能只涉及两个指针分配。

另一方面,使用 std::shared_ptr 和复制涉及不必要的 atomic 递增(用于创建副本)和递减(用于破坏原件)。对于当今的缓存密集型多核处理器来说,原子操作当然远非便宜。

因此,只要坚持代码的预期语义(唯一所有权,用 std::unique_ptr 惯用地表达),您将获得良好的性能作为奖励。