std::shared_ptr<type>(new DerivedType(...)) != std::make_shared<type>(DerivedType(...))?

std::shared_ptr<type>(new DerivedType(...)) != std::make_shared<type>(DerivedType(...))?

我还没有发现任何类似这样的问题:但如果有人找到了,那就抱歉了。 我一直在尝试使用 std::shared_ptr 来大大简化内存管理,但是我遇到了一定是某种错误。

当我用 std::make_shared<type>(DerivedType(...)) 创建一个 DerivedType 指针时,它只能作为 Type 而不是 DerivedType 来寻址。

然而,当我使用语法 std::shared_ptr<Type>(new DerivedType) 时,vfptr table 列出了正确的条目,并且可以毫无问题地转换为 DerivedType

我相信应该没有区别。这是我理解中的错误吗?还是真正的错误?

感谢您的帮助。 卢克

std::make_shared<type>(DerivedType(...))

HERe 将 make_shared<Type> 替换为 make_shared<DerivedType>,这一切都应该有效

更新:突出显示更改

您必须将要传递给类型的构造函数的参数传递给 std::make_shared,并且它们是 转发
然后您可以将结果指针隐式转换为基指针。

std::shared_ptr<Type> p = std::make_shared<DerivedType>(...);

让我们深入了解一下您问题中的 "why"。

std::shared_ptr<Type>(new DerivedType);

这确实有效,但没有任何值得注意的地方。但是,通常首选 std::make_shared,因为后者可以将 std::shared_ptr 的簿记数据与您的对象一起分配,因此速度更快,成本更低,并且异常安全*。

std::make_shared<Type>(DerivedType(...))

你看到了:它不起作用。这里发生的是您创建了一个 DerivedType 实例。 std::make_shared愉快地转发给Type的构造函数。
发生重载解析,并调用 Type 复制构造函数 (或其移动构造函数,如果可用),并引用您的 DerivedType 的基础部分.一个普通的 Type 对象被实例化并指向。原来的 DerivedType 消失了。这个问题作为一个整体被称为 slicing.

* 关于异常安全的注意事项: 你应该使用以下形式的函数吗:

void func(std::shared_ptr<A> a, std::shared_ptr<B> b);

... 像这样构建 std::shared_ptrs :

func(std::shared_ptr<A>(new A), std::shared_ptr<B>(new B);

... 如果调用 new A,然后调用 new B,则可能会泄漏,后者会抛出异常。 A还没有被包装成智能指针,无法恢复。