从向量中按内存地址删除共享指针

Posted

技术标签:

【中文标题】从向量中按内存地址删除共享指针【英文标题】:Delete shared pointer by memory address from vector 【发布时间】:2020-10-16 23:05:14 【问题描述】:

我有一个包含共享指针的向量。我想通过使用它的内存地址从列表中删除一个指针,这可能吗?或者有没有更好的方法来存储共享指针的集合?


std::vector<std::shared_ptr<Person>> list;

void removePerson(const std::shared_ptr<Person>& person) 
                auto remove = std::remove(list.begin(), list.end(), person);
                list.erase(remove, list.end());
    

【问题讨论】:

“它的内存地址”是指指针的值(即shared_ptr指向的Person对象的内存位置),还是指针的地址(即shared_ptr的内存位置对象本身,位于向量的内部项目数组内)? 如果您想按值快速查找,std::setstd::unordered_set 将分别为您提供 O(log(N))O(1) 查找时间,两者都比 O(N) 按值查找快得多std::vector 的时间(尽管只有当您维护的 shared_ptrs 数量很大时,性能差异才会明显,例如数百/数千或更多) 这不是调用list.erase 删除所有要删除的项目吗? list.erase(remove); 应该被调用以从向量中删除单个项目。 这可能吗?你尝试的时候发生了什么? 【参考方案1】:

是的,可以按地址从指针容器中删除指针。

虽然std::vector&lt;std::shared_ptr&lt;T&gt;&gt;一种存储共享指针的普通方式,但如果不了解您的需求,就无法回答哪种方式更好的问题。

这是您模板的扩展,用于演示按地址删除指针,使用您自己的 removePerson() 函数:

#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

// A minimal Person type for demonstration purposes
struct Person 
    Person(const std::string& n): name(n) 
    std::string name;
;

// Original template
std::vector<std::shared_ptr<Person>> persons;

void removePerson(const std::shared_ptr<Person>& person) 
    auto remove = std::remove(persons.begin(), persons.end(), person);
    persons.erase(remove, persons.end());


int main()

    auto bob = std::make_shared<Person>("bob");

    // Include bob multiple times to demonstrate multiple removal
    persons.emplace_back(bob);
    persons.emplace_back(std::make_shared<Person>("alice"));
    persons.emplace_back(bob);
    persons.emplace_back(std::make_shared<Person>("carol"));
    persons.emplace_back(bob);

    // Define a lambda for debugging output
    auto printPersons = [&] (const auto& header) 
        std::cout << header << std::endl;
        for(auto& p: persons)
            std::cout << p->name << std::endl;
    ;

    printPersons("== Before ==");
    removePerson(bob);
    printPersons("\n== After ==");

这会产生以下输出:

== Before ==
bob
alice
bob
carol
bob

== After ==
alice
carol

注意:std::vector 通常不会命名为 list,因为它不是一个列表;-)

【讨论】:

请注意,std::remove() 将扫描整个向量。如果指针仅在向量中存储一次,则应使用 std::find() 代替,然后使用 erase() 唯一的迭代器,如果它不是结束迭代器则返回。

以上是关于从向量中按内存地址删除共享指针的主要内容,如果未能解决你的问题,请参考以下文章

指针和指针的地址如何共享同一个内存地址? [复制]

这种对共享指针向量的回退是不是会导致内存泄漏?

指针在删除它并在c ++中再次分配新内存后是不是获得相同的内存地址?

将向量地址转换为本机指针是不是安全?

mmap共享内存深入总结

物理内存虚拟内存bufferscached共享内存swap