如何在将向量<derived *>转换为向量<base *> </base *> </derived *>时避免复制

时间:2011-09-26 09:14:33

标签: c++ casting copy stdvector

有没有办法避免复制大型向量,当一个函数需要一个带有(指向)基类对象的向量作为输入,但我只有一个(指向)派生对象的向量?

class Base {};

class Derived : public Base {};

void doStuff(vector<Base*> &vec)
{
    //do stuff with vec objects
}

int main()
{
    vector<Derived*> fooDerived(1000000);

    vector<Base*> fooBase(fooDerived.begin(), fooDerived.end()); // how to avoid copying here?
    doStuff(fooBase);
}

6 个答案:

答案 0 :(得分:2)

如果您可以使用vector<Derived*>,就好像vector<Base*>那样,您可以向该向量添加指向class OtherDerived : public Base的指针。这将是危险的。

答案 1 :(得分:1)

你无法施放矢量。但是,你不应该真的需要。

如果您真的想要,可以使用Boost Iterator(documentation

static Derived* ToDerived(Base* b)
{
    return dynamic_cast<Derived*>(b); // return null for incompatible subtypes
}

static void DoSomething(Derived* d)
{ 
          if (!d)
               return; // incompatible type or null entry
          // do work
}


// somewhere:
{
    std::vector<Base*> bases;

    std::for_each(
         boost::make_transform_iterator(bases.begin(), &ToDerived),
         boost::make_transform_iterator(bases.end(), &ToDerived),
         DoSomething);
}

注意:使用 dynamic_cast<Derived*> 的一个特别方便的效果是,如果对象的运行时类型无法转换为Derived*(例如因为它实际上是OtherDerived*,它只会返回一个null指针。

答案 2 :(得分:1)

如果您对doStuff()的定义是绝对必要的,那么您将无法绕过副本。出于各种原因,指针的容器与指针的类层次结构不是“协变的”。 (例如,如果您可以将vector<Derived*>视为vector<Base*>,则可以将Base - 指针插入其中,这些指针的行为与Derived不同 - 指针。无论如何,容器的参数类型是固定的,也是容器类型的一部分。)

如果你对这个函数有一些余地,你可以稍微重构一下代码:你可以把它变成一个参数化的模板,或者一个迭代器范围的模板,和/或你可以将实际的工作量分成一个单独的功能。例如:

void doStuffImpl(Base *);

template <typename Iter>
void doStuff(Iter begin, Iter end)
{
  for (Iter it = begin; it != end; ++it)
  {
    doStuffImpl(*it);  // conversion happens here
  }
}

答案 3 :(得分:0)

由于vector的模板是指针,因此fooBase局部变量将使用reference。也许这个问题不是很清楚,如果你能明确指出我们可能会试图解决这个问题!

答案 4 :(得分:0)

一种方法是只存储指向基类的指针,如下所示:

vector<Base*> v(100);
v.push_back(new Derived());

doStuff(v);

答案 5 :(得分:0)

我发现this topic有趣的地方,他们提到你可以安全地将Derived*投放到Base*(但不是另一边),而vector<Derived*>到{{{ 1}}但你应该能够...(好的,矢量的地址发生了变化,因此需要一份副本
他们提到的一个肮脏的解决方案是使用vector<Base*>,但不确定它是否比使用复制构造函数更好......可能会发生同样的事情。