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

当我使用DerivedType创建std::make_shared<type>(DerivedType(...))指针时,只能将其寻址为Type而不是DerivedType

但是,当我使用语法std::shared_ptr<Type>(new DerivedType)时,vfptr表列出了正确的条目,并且可以将其强制转换为DerivedType而不会有问题。

我相信应该没有区别。就我所知这是一个错误吗?还是一个实际的错误?

谢谢你的帮助。
路加

最佳答案

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

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


让我们来探讨一下问题的“原因”。

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消失了。整个问题称为切片。

*关于异常安全性的注意事项:请使用以下形式的函数:

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


...像这样构造std::shared_ptr

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


例如,如果调用new A,然后调用new B,后者会引发异常,则可能会泄漏。 A尚未包装到智能指针中,并且无法恢复。

09-06 08:50