【问题标题】:C++ - How to delete shared_ptr from vector based on it's value [duplicate]C ++ - 如何根据它的值从向量中删除shared_ptr [重复]
【发布时间】:2020-09-16 11:39:39
【问题描述】:

我有以下课程:

public:
    Client(tcp::socket socket)
    : socket_(std::move(socket))
    {
    }
    void start();
    int connectionId;

比我有以下向量:

class Server {
public:
    Server();
    static std::vector<std::shared_ptr<Client>> Clients;
}

编辑*

我可以这样做吗:

for (int i = 0; i < Server::Clients.size(); ++i) {
    if(Server::Clients[i]->connectionId == connectionId)
        Server::Clients.erase(Server::Clients.begin()+i);
}

我的问题是如何使用特定的connectionId 也就是按值删除来删除Clients 中的共享指针?

【问题讨论】:

    标签: c++ vector shared-ptr


    【解决方案1】:

    在 C++17 中,您可以使用 std::remove_if。以下应该可以工作。

    #include <algorithm>
    
    Server &s = /* <getServerFromSomewhere> */;
    auto new_end = remove_if(s.Clients.begin(), s.Clients.end(),
        [] (std::shared_ptr<Client>& p) {
            return p->connectionId == /* <someValueToBeRemoved> */;
        }
    );
    s.Clients.resize(new_end - s.Clients.begin());
    

    【讨论】:

      【解决方案2】:

      使用 std::remove_if 和 lambda 作为谓词,然后使用容器的方法 erase

      std::vector<std::shared_ptr<Client>> Clients;
      int id{0}; // the id to be removed
      Clients.erase(std::remove_if(Clients.begin(), Clients.end(), [id](const auto &entity) { return id == entity->connectionId; }), Clients.end());
      

      【讨论】:

        【解决方案3】:

        如果您无权访问std::remove_if,则必须退回到某种循环:

        auto it = Clients.begin()
        
        while (it != Clients.end())
        {
            if((*it)->connectionId = testValue)
            {
                 // can connection id be non-unique?
                 it = Clients.erase(it);
                 //if yes, we have to save new iterator
                 continue;
            }
            it++;
        }
        

        如果connectionId 是唯一的,请使用 find_if 查找该元素并将其删除,这样会更便宜。

        如果remove_if 可用,以下代码是可能的,如果它比第一个示例的优势值得怀疑。

        auto new_end = remove_if(s.Clients.begin(), s.Clients.end(),
            [=] (auto& ptr) {
                return ptr->connectionId ==  testValue; /* value to be removed */
            }
        erase(new_end, Clients.end()); // remove tail of vector that is now consisting of empty elements.
        

        Clients 最好是 deque 而不是矢量,这样从其中删除元素不会导致每次删除完成时都复制 Clients 列表的“尾部”部分。

        【讨论】:

        • 我已对我的问题进行了编辑。我可以按照我在问题中标记的那样去吗?
        • “都删除一个元素” - 不,他们不会都删除一个元素。如果仅使用remove,向量的大小保持相同。这个成语被称为“erase-remove”是有原因的。
        • @StoryTeller-UnslanderMonica 他没有这样做,他奇怪的是在反向循环中这样做
        • 不,他正在这样做。循环是另一个奇怪的地方,但他确实 try 正确使用了这个成语。说“为什么你同时使用remove_if和erase?都删除一个元素”这样的话是错误的并且具有误导性。
        • 伙计们,我已经更新了我的问题。我可以像问题中描述的那样正确地从向量中删除吗?
        猜你喜欢
        • 2021-11-13
        • 2014-07-04
        • 1970-01-01
        • 2015-09-15
        • 1970-01-01
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 2016-04-18
        相关资源
        最近更新 更多