【问题标题】:C++ change list while iterating?迭代时C ++更改列表?
【发布时间】:2021-07-13 16:02:33
【问题描述】:

C++11 中有一个名为 jobs 的列表,我想在其中删除所有停止标志为 true 的作业,所以我写道:

auto job = jobs.begin();
while (job != jobs.end()) {
    if (!job->stopped) {
        job = jobs.erase(job)
    } else {
        ++job;
    }
}

但是有人看了我的代码说错了,我不明白为什么?

【问题讨论】:

  • 他们没有告诉你为什么错了?也许他们只是不理解代码
  • 也许它是错误的,因为我们在这段代码中没有看到 sn-p 的原因 - 或者它可能是“错误的”,因为如果你使用 std::vector,这将是一种低效的方式(请参阅下面@PaulMcKenzie 的评论以获得更好的选择 - 如果您使用的是 C++20,请参阅 std::erase_if)。
  • jobs.erase(std::remove_if(jobs.begin(), jobs.end(), [&](auto& job) { return job.stopped; }), jobs.end());
  • 我个人会改用for 循环。获得job 的自动作用域,但除此之外(以及缺少的分号),您的代码看起来还不错。您确实需要与“某人”交谈并让他们为您提供更多详细信息。
  • @anastaciu :-) 我std::promise我没有。

标签: list for-loop c++11 stl iterator


【解决方案1】:

如果不考虑与此语句中缺少的分号相关的错字

job = jobs.erase(job)
                    ^^^

以及在这种情况下的第二个错字

if (!job->stopped) {
    ^^^^

应该这样写

if ( job->stopped) {

(即您在编写所有带有设置标志stopped 的作业时需要删除)您的代码是正确的,但是是多余的。

你可以写

jobs.remove_if( []( const auto &job ) { return job.stopped; } );

jobs.remove_if( []( const JobEntry &job ) { return job.stopped; } );

如果在成员函数中调用此语句。

编辑:这是一个使用您的类声明的演示程序。

#include <iostream>
#include <string>
#include <list>
#include <ctime>

typedef int pid_t;

class JobsList {
public:
    class JobEntry {
    public:
        pid_t pid, jid;
        std::string cmd;
        time_t in_time;
        bool stopped;

        JobEntry( int pid, int jid, const std::string &cmd, bool stopped )
            :pid( pid ), jid( jid ), cmd( cmd ), stopped( stopped )
        {}
        // TODO: Add your data members

        bool operator<( JobEntry const &tmp ) const {
            return jid < tmp.jid;
        }

        bool operator==( JobEntry const &tmp ) const {
            return jid == tmp.jid;
        }
    };
    std::list<JobEntry> jobs;
};

int main()
{
    JobsList jobs_list =
    {
        {
            { 1, 1, "first", false },
            { 2, 2, "second", true }
        }
    };

    std::cout << jobs_list.jobs.size() << '\n';
    jobs_list.jobs.remove_if( []( const auto &job ) { return job.stopped; } );
    std::cout << jobs_list.jobs.size() << '\n';
}

为了简单起见,我只介绍了这个 typedef

typedef int pid_t;

并在构造函数中更改了参数声明

JobEntry( int pid, int jid, const std::string &cmd, bool stopped )
                            ^^^^^^^

【讨论】:

  • 抱歉,您的代码不起作用,我得到:在模板中:没有匹配函数调用类型为 '(lambda at /Users/me/CLionProjects/OS1_WET/Commands.cpp:305 :21)' 在函数模板特化 'std::list<:jobentry>::remove_if' 的实例化中发生错误此处请求类型为“void (*)(int &)”的转换候选
  • @john 这不是我的代码不起作用。这是您的代码不起作用。我没有看到你的代码。所以你需要提供一个最小的完整程序来演示这个问题。
  • @john 这是 Vlad 的解决方案,适用于您在 cmets 中提到的 waitpid 版本:godbolt.org/z/WPsaGjoWq
猜你喜欢
  • 1970-01-01
  • 2019-06-07
  • 2016-03-16
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 2014-09-17
  • 2012-05-05
  • 1970-01-01
相关资源
最近更新 更多