如何在转换向量时避免复制到向量

发布于 2024-12-06 06:32:29 字数 405 浏览 1 评论 0 原文

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

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);
}

Is there a way to avoid copying large vectors, when a function expects a vector with (pointer to) baseclass objects as input but I only have a vector of (pointers to) derived objects?

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

和影子一齐双人舞 2024-12-13 06:32:29

如果您可以像使用 vector 一样使用 vector ,则可以添加一个指向 OtherDerived 类的指针: public Base 到该向量。这会很危险。

If you could use a vector<Derived*> as if it where a vector<Base*>, you could add a pointer to a class OtherDerived : public Base to that vector. This would be dangerous.

笑,眼淚并存 2024-12-13 06:32:29

您无法投射向量。但是,您实际上也不需要这样做。

如果你真的想要,你可以使用Boost Iterator (文档

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* (例如,因为它实际上是一个 OtherDerived*,所以它只会返回一个 null 指针。

You can't cast the vectors. However, you shouldn't really need to either.

If you really want, you could use 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);
}

Note: a particularly handy effect of using dynamic_cast<Derived*> is that if the runtime type of the object cannot be casted to Derived* (e.g. because it is actually an OtherDerived*, it will simply return a null pointer.

爱格式化 2024-12-13 06:32:29

如果您对 doStuff() 的定义是绝对强制的,那么您将无法绕过副本。由于多种原因,指针的容器相对于被指向者的类层次结构不是“协变”的。 (例如,如果您可以将 vector 视为 vector,则可以插入 Base 指针无论如何,容器的参数类型是固定的,并且是容器类型的一部分。)

如果您对该函数确实有一些余地,那么您 可以使用派生指针。可以重构代码一点:您可以将其设置为容器上参数化的模板,或者迭代器范围上的模板,和/或者您可以将实际工作负载拆分为单独的函数。例如:

void doStuffImpl(Base *);

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

If your definition of doStuff() is absolutely mandatory, then you won't get around the copy. Containers of pointers aren't "covariant" with respect to the pointee's class hierarchy, for a whole host of reasons. (For example, if you could treat vector<Derived*> like a vector<Base*>, you could insert Base-pointers into it which wouldn't behave like Derived-pointers. In any event, the parameter type of a container is fixed and part of the container's type.)

If you do have some leeway with the function, you could restructure the code a bit: You could make it a template parametrized on the container, or a template on an iterator range, and/or you could split the actual workload into a separate function. For example:

void doStuffImpl(Base *);

template <typename Iter>
void doStuff(Iter begin, Iter end)
{
  for (Iter it = begin; it != end; ++it)
  {
    doStuffImpl(*it);  // conversion happens here
  }
}
烟雨扶苏 2024-12-13 06:32:29

由于向量的模板是一个指针,因此您的 fooBase 局部变量将使用引用。可能问题不是很清楚,如果您能说清楚的话我们可能会尽力解决问题!

Since your template for the vector is a pointer, your fooBase local variable is going to be using reference. Maybe the question is not very clear, if you could specify clearly we may try to address the problem!

决绝 2024-12-13 06:32:29

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

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

doStuff(v);

One way is to store only pointers to the base class like this:

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

doStuff(v);
总以为 2024-12-13 06:32:29

我发现这个主题很有趣,他们提到你可以安全地转换Derived*< /code> 到 Base* (但不是另一侧),而从 vectorvector< 是不可能的/code> 但你好心of 应该能够...(好吧,向量的地址发生变化,因此需要一个副本
他们提到的一个肮脏的解决方案是使用reinterpret_cast >(vector)
但不确定它是否比使用复制构造函数更好......可能会发生同样的事情。

I found this topic interesting where they mention you can safely cast Derived* to Base* (but not the other side) while this is not possible from vector<Derived*> to vector<Base*> but you kind of should be able to... (Ok, the address of the vector changes, thus needing a copy)
One dirty solution they mention is using reinterpret_cast<vector<Base*> >(vector<Derived*>) but not sure if it's better then using the copy constructor... probably the same thing happens.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文