gpt4 book ai didi

c++ - 传递派生共享指针的 vector ?

转载 作者:太空狗 更新时间:2023-10-29 21:41:26 25 4
gpt4 key购买 nike

允许将指向派生类的共享指针 vector 传递给一个函数的正确方法是什么,该函数需要指向基类的共享指针 vector 而不执行复制?

代码如下:

#include <string>
#include <vector>
#include <memory>

class Base {
public:
std::string Name;
};
using BaseList = std::vector<std::shared_ptr<Base>>;

class Derived : Base {
};
using DerivedList = std::vector<std::shared_ptr<Derived>>;

class BaseHandler {
public:
void process( BaseList list ) {
}
};

int main() {

DerivedList list;

BaseHandler bh;
bh.process( list );

}

代码链接:http://coliru.stacked-crooked.com/a/5a5b18ba3b2a4f08

编辑:DOH!!!我发错了。抱歉...这是 shared_ptr 一个。

最佳答案

你可以试试这个。

template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& t) { std::cout << "process" << std::endl; }

主要思想是:

  1. 我们可以通过编译器已知的具体类型信息访问元素,而不是通过基类指针访问元素。
  2. 这个函数模板使用了一个叫做“SFINAE”的技巧来检查参数是否是派生类的智能指针的容器。


跟进:

从“指向派生类的共享指针的容器”到“指向基类的共享指针的容器”的转换是可能的,而且不是很困难。但是,我担心使用“指向基类的共享指针容器”的设计选择是否会给您带来可接受的性能。


让我们先讨论一下如何去做。

  1. 我们可以创建一个 std::shared_ptr<Base>来自每个 std::shared_ptr<Derived> 的对象使用 std::static_pointer_cast 对象.
  2. 申请std::static_pointer_cast在列表的所有条目上,我们可以使用 std::transform .
  3. 如果您有许多派生类,则可以使用带有 SFINAE 检查的函数模板(如前所述)使每个派生类都可以进行转换。

因此,代码如下所示:

DerivedList derivedList;
// Put items into derivedList

BaseList baseList;
baseList.reserve(derivedList.size());
std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const std::shared_ptr<Derived>& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});

BaseHandler bh;
bh.process(baseList);

或者:

class BaseForwarder
{
public:
template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& derivedList)
{
BaseList baseList;
baseList.reserve(derivedList.size());

std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const SharedPtr& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});

BaseHandler bh;
bh.process(baseList);
}
};

但是,这种方法有相当多的性能损失。

  • 必须为每个派生类指针列表创建一个新的基类指针列表。构建新列表会花费大量时间和内存。
  • 对象是通过指针访问的。这种间接减慢了速度。
  • 由于对象没有分配到紧凑的数据结构中,缓存未命中会很严重。

我建议您评估性能,看看这种方法是否可以接受。否则,最好考虑一些其他的设计选择。

关于c++ - 传递派生共享指针的 vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28823540/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com