lfg*_*gtm 1 c++ shared-ptr make-shared c++17
考虑这个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;
}
Run Code Online (Sandbox Code Playgroud)
总之:
返回std::make_shared<T>似乎工作正常,并允许调用者正确投射。(见A())。
使用make_shared<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>推荐 over std::shared_ptr<T>(new T(...)),是否有任何例外意味着不推荐它?
我不熟悉什么
make_shared<T>给
它创建一个T(在堆上,将它包装在 a 中shared_ptr)。它完全且仅 创建T. 您的make_shared<Base>电话相当于new Base(Derived(1, 2)。这将构造一个Base(通过从给定Derived的Base子对象复制,通常称为“切片”,因为您只是复制对象的一部分),因为这是您给它的类型。
Derived这些shared_ptrs 中没有,因此您不能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与您创建错误的类型无关,而与此无关。