考虑这个例子,用各种方式构造shared_ptr<T>
并返回:
#include <memory>
#include <iostream>
class Base
{
public:
virtual ~Base() {}
Base(int y) : y_(y) {}
int y_;
};
class Derived : public Base
{
public:
Derived(int y, int z) : Base(y), z_(z) {}
int z_;
};
std::shared_ptr<Base> A()
{
return std::shared_ptr<Base>(new Derived(1, 2));
}
std::shared_ptr<Base> B()
{
std::shared_ptr<Derived> result = std::make_shared<Derived>(Derived(1, 2));
return result;
}
std::shared_ptr<Base> C()
{
std::shared_ptr<Base> result = std::make_shared<Base>(Derived(1, 2));
return result;
}
std::shared_ptr<Base> D()
{
return std::make_shared<Base>(Derived(1, 2));
}
int main(int argc, char** argv)
{
// Works fine...
std::shared_ptr<Derived> resultA = std::dynamic_pointer_cast<Derived>(A());
// Works fine...
std::shared_ptr<Derived> resultB = std::dynamic_pointer_cast<Derived>(B());
// Does not cast to base? ...
std::shared_ptr<Derived> resultC = std::dynamic_pointer_cast<Derived>(C());
// Object returns fine (of type Base), but cannot be cast to Derived?
std::shared_ptr<Base> resultCBase = C();
std::shared_ptr<Derived> resultCDerived = std::dynamic_pointer_cast<Derived>(resultCBase);
// Does not cast to derived...
std::shared_ptr<Derived> resultD = std::dynamic_pointer_cast<Derived>(D());
return 0;
}
总结:
返回std::make_shared<T>
似乎工作正常,并允许调用者正确地进行强制转换。(参见A()
(。
使用make_shared<Derived>
创建Derived,然后依靠隐式强制转换返回shared_ptr<Base>
可以工作,并允许调用方正确强制转换。(参见B()
(。
然而,对于C()
和D()
,当使用make_shared<Base>(Derived(...))
时,shared_ptr<Base>
被构造(似乎是正确的(,但不能转换为std::shared_ptr<Derived>
?
我不熟悉make_shared<T>
给出了什么(尽管SO的其他答案暗示了更好的类型安全性和单一分配?(,但它的执行或行为似乎与用std::shared_ptr<T>(new T(...))
替换时不同?
有人能向我解释一下这里发生了什么,以及为什么它没有像我预期的那样起作用(我认为我用错了,或者在使用它时我应该知道一些微妙的行为特征(吗?
由于上述示例具有差异,因此A()
&B()
正在工作,但没有C()
和D()
(假设我使用正确(。。。为什么make_shared<T>
被推荐而不是std::shared_ptr<T>(new T(...))
,是否有任何例外情况意味着它不被推荐?
我不熟悉
make_shared<T>
给带来了什么
它创建一个T
(在堆上,用shared_ptr
包装它(。它只创建T
。您的make_shared<Base>
呼叫相当于new Base(Derived(1, 2)
。这将构造一个Base
(通过从给定的Derived
的Base
子对象复制,通常称为"切片",因为你只复制了对象的一部分(,因为这是你给它的类型
在这些shared_ptr
中没有Derived
,因此不能将dynamic_pointer_cast
转换为该类型。
然而,它的执行或行为方式似乎与用
std::shared_ptr<T>(new T(...))
替换时不同
为什么推荐
make_shared<T>
而不是std::shared_ptr<T>(new T(...))
,
std::shared_ptr<Base>(new Base(Derived(1, 2)))
也会出现完全相同的问题。这与make_shared
无关,而是与您创建了错误的类型有关。