将标准::指针列表转换为标准::值列表的快速方法

Fast way to convert std::list of pointer to std::list of value

本文关键字:标准 列表 方法 转换 指针      更新时间:2023-10-16

我有一个std::list<obj*>,其中obj是我的类:

std::list<obj*> list_of_ptr;
list_of_ptr.push_back(new obj());

我想将此列表转换为等效std::list<obj>,之后我不再需要list_of_ptr

完成这项工作的最快方法是什么?

>std::transform是你的朋友:

std::vector<obj> objects;
std::transform(
    list_of_ptr.begin(), list_of_ptr.end(),
    std::back_inserter(objects), 
    [](obj* p) { return *p; });

或者,如果无法使用 C++11 lambda 表达式,则可以使用简单的函数对象来执行间接寻址:

struct indirect
{
    template <typename T>
    T& operator()(T* p) { return *p; }
};
std::transform(
    list_of_ptr.begin(), list_of_ptr.end(),
    std::back_inserter(objects), 
    indirect());

或者,使用 boost::indirect_iterator

std::vector<obj> objects(
    boost::make_indirect_iterator(list_of_ptr.begin()),
    boost::make_indirect_iterator(list_of_ptr.end()));

当然,这些假设序列中没有空指针。 它留给读者一个练习,以弄清楚如何正确管理list_of_ptr中的指针所指向的对象的生存期。

理想情况下,从一开始就使用std::vector<obj>,或者,如果不可能,则使用智能指针的容器。 手动管理指向对象的生存期并正确执行此操作非常困难。 C++具有很棒的自动对象生存期管理工具(析构函数,智能指针,容器,堆栈语义,RAII),并且没有理由不使用它们。

简单易懂的代码也是你的朋友:

for each (obj* pObj in list_of_ptr)
{
    if (pObj != nullptr)
    {
        list_of_objects.push_back(*pObj);
    }
}

如果这不适合您,这当然应该:

std::list<obj> list_of_objects;
for_each(list_of_ptr.begin(), list_of_ptr.end(), [&list_of_objects] (obj* pObj) {
    if (pObj != nullptr)
        list_of_objects.push_back(*pObj);
});