【问题标题】:Add struct in std::list在 std::list 中添加结构
【发布时间】:2021-07-14 09:15:03
【问题描述】:

我有以下结构:

struct data {
    std::string str;
    int num;
    int num2;
    std::string str2
} data1;

我有一个std::list<struct data> list

我想在std::list中添加struct,假设没有这样的结构,使用std::find_if和lambda函数。

std::list<data>::iterator it = std::find(list.begin(), list.end(), data1);
if (it == list.end()) list.push_back(data1)

你怎么能做到这一点?

【问题讨论】:

  • 我为我的答案添加了一个解决方案,看看它是否适合你。
  • 我做了,但我想用 std::find_if 和 lambda 函数的
  • @ivanovIAVDD 是否需要使用 find_if 和 lambda?
  • 如果您提供散列函数和operator==,您可以使用std::set
  • @Ted Lyngmo,是的,我必须使用 find_if 和 lambda

标签: c++ iterator find stdlist


【解决方案1】:

您没有正确声明std::list。确保仅指定数据类型。在这种情况下,声明应该是std::list&lt;data&gt; list;

之后,您可以创建 data 类型的对象,并使用 push_back 将它们存储在 std::list 中。

【讨论】:

  • std::list&lt;struct data&gt; list 中的struct 关键字是有效的,但在这种情况下不需要(查找c++ 可以确定data 指的是struct)。如果您 - 此外 - 还有一个名称为 data 的函数,则需要 struct 关键字。
  • 感谢您指出@t.niese,我不知道这一点。
  • 在添加之前,我想检查列表中是否存在这样的项目
【解决方案2】:

您可以迭代列表并将要添加的对象与现有对象进行比较,您可以通过比较所有数据成员来做到这一点,如果它们匹配则对象相等。我建议实现一个自定义比较运算符,而不是每次需要比较对象时比较数据成员:

struct data
{
    std::string str;
    int num;
    int num2;
    std::string str2;

    bool operator==(const data &d)
    {
        return this->num == d.num && this->str == d.str && this->num2 == d.num2 && d.str2 == this->str2;
    }
};

用于 lambda 和 std::find_if()

data d{"string1", 2, 2, "string2"}; 

std::list<data>::iterator it = std::find_if(list.begin(), list.end(), [&](const data& dt) {
    return d == dt;         
});

if(it == list.end())
{
    list.push_back(d);
}

请注意,正如评论部分中的@Remy pointed out,使用std::find() 而不是std::find_if() 可以更轻松地实现这一点:

std::find(list.begin(), list.end(), d); // comparator implementation also needed

【讨论】:

  • 请注意,在实现operator== 后,可以使用std::find(list.begin(), list.end(), d) 代替std::find_if(),不需要lambda。我知道这不是要求,但应该注意。
  • @RemyLebeau 注意到,我链接了评论,请不要删除它。
  • 谢谢!我使用 std::find。
【解决方案3】:

要使用 std::find_if 和 lambda:

std::list<data>::iterator it = std::find_if(list.begin(), list.end(),
    [&data1](const data& rhs) {
        return
            data1.str == rhs.str &&
            data1.num == rhs.num &&
            data1.num2 == rhs.num2 &&
            data1.str2 == rhs.str2;
    }
);

在这种情况下,我建议定义 data::operator== 并改用 std::find

struct data {
    std::string str;
    int num;
    int num2;
    std::string str2;

    bool operator==(const data& rhs) const {
        return
            str == rhs.str &&
            num == rhs.num &&
            num2 == rhs.num2 &&
            str2 == rhs.str2;
    }
};

std::list<data>::iterator it = std::find(list.begin(), list.end(), data1);

在 C++20 中,您可以通过默认 operator&lt;=&gt;宇宙飞船运算符)来简化此操作:

默认的&lt;=&gt; 重载还允许将类型与&lt;&lt;=&gt;&gt;= 进行比较。如果operator&lt;=&gt; 是默认的,而operator== 根本没有声明,那么operator== 是隐式默认的。

鉴于此,以下是允许使用所有这些运算符比较 data 的方法:

struct data {
    std::string str;
    int num;
    int num2;
    std::string str2;

    friend auto operator<=>(const data&, const data&) = default;
};

【讨论】:

  • 啊……宇宙飞船操作员,优秀的补充。
  • @anastaciu 我不能说我已经完全理解了它的所有用途,并且还没有在我自己的任何程序中实际使用过它:-) 不过它看起来真的很通用。
  • 作为所有新事物,需要时间来解决。在你提到它之前,我什至不记得它。我也觉得很有趣。
猜你喜欢
  • 2015-04-20
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
相关资源
最近更新 更多