有没有办法避免复制大型向量,当一个函数需要一个带有(指向)基类对象的向量作为输入,但我只有一个(指向)派生对象的向量?
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);
}
答案 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*>
,但不确定它是否比使用复制构造函数更好......可能会发生同样的事情。