繁体   English   中英

这段代码安全吗? 施放std :: vector <Derived*> 到std :: vector <Base*>

[英]is this code safe? cast a std::vector<Derived*> to std::vector<Base*>

基本上我有一个class A和一个class B : public A

我想将std::shared_ptr<std::vector<A*>转换为std::shared_ptr<std::vector<B*>

问题是std::vector<B>不从std::vector<A>继承,而smart_ptr也没有。 所以我做了一个可怕的演员

  std::shared_ptr<VectorA> vector_a = * ((std::shared_ptr<VectorA>*)&vector_b);

代码编译并在那里运行,但它是安全的吗? http://liveworkspace.org/code/3dQTz1$0

这是一个可怕的解决方案。 当您将一种类型的对象向量转换为另一种类型时,您可能会遇到所有类型的错误/未定义行为。

您应该从头开始使用std::shared_ptr<A>向量,并使用指向B类型对象的指针对它们进行初始化。

如果不可能,您可以创建一个包含std::weak_ptr<A>的新向量,以避免两次管理这些对象。

不要那样做。

考虑到(指向) B的向量不是(指向) A的向量,或者更确切地说,不是对(指针) A的向量的通用有效替换; 因此,有充分的理由说明你无法进行这样的转换。

虽然你在B的向量中所拥有的确实是一组对象(也是( A实例,考虑以下算法:

void f(vector<A>& v)
{
    A a;
    v.push_back(a);
}

现在假设你用向量B调用f() 这将尝试将不是B的类的实例添加到应该仅包含类型B元素的集合中。

这里的解决方案是使代码只接受一个足够灵活的vector<A> ,以便在vector<B> 换句话说,您需要将其设为模板。 例如,您的模板只能接受从A派生的类型的向量作为参数。 使用一些SFINAE技术和类型特征(如std::is_base_of可以很容易地实现这一点。

严格来说,解除引用操作应该会成功。 两个向量都是指针容器,因此将一个转换为另一个,虽然生产代码不可接受,但仍将使用相同的尺寸和对齐方式。

C ++提供了丰富的抽象来避免这些恶作剧,但最好将派生对象的向量填充为基类的指针。

你仍然可以投射元素:

A* a = vector_b->at (42);

给你你想要的。

现在,如果你已经编写了将shared_ptr<vector<A*>>作为参数编写的函数,那么你有多个解决方案可以让你摆脱这种情况:

  • 使用shared_ptr<A*[]> shared_ptr<vector<A*>>而不是shared_ptr<vector<A*>> (它可以按您的意愿工作)
  • A**作为参数(并使用vector_b->data () ):它不会将您vector_b->data ()到共享指针。
  • 更好:采取迭代器,其解引用为[智能]指针A (回想operator->链)
  • 使用std::vector<std::shared_ptr<A>> (浪费资源)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM