为什么在 boost multi_index 容器中插入新元素时所有元素都会被替换?

Why does all elements get replaced when inserting new elements in boost multi_index container?

当我在其他元素正确插入后插入主函数时,但是当我尝试通过函数执行此操作时,所有值都被最后一个元素替换。

请参考以下代码:

struct X
{
    std::string panelid; // assume unique
    std::string messageid; // assume unique
    std::string tid; // assume non-unique
    std::string name;
};
struct IndexByPanelID {};
struct IndexByMessageID {};
struct IndexByTID {};

typedef  boost::multi_index_container<
        X*, // the data type stored
        boost::multi_index::indexed_by< 
        boost::multi_index::hashed_non_unique<  
        boost::multi_index::tag<IndexByPanelID>, 
        boost::multi_index::member<X, std::string, &X::panelid> 
        >,
        boost::multi_index::hashed_non_unique<  
        boost::multi_index::tag<IndexByMessageID>, 
        boost::multi_index::member<X, std::string, &X::messageid>
        >,
        boost::multi_index::hashed_non_unique<  
        boost::multi_index::tag<IndexByTID>, 
        boost::multi_index::member<X, std::string, &X::tid> 
       >
     >
> Container;
int Insert(X newframe, Container *Cont)
{
    auto& indexByL = c.get<IndexByPanelID>();
    indexByL.insert(&newframe);
    return 0;
}
int main()
{
    Container c;  // empty container
    X x1{ "1", "80", "FE01", "0712"};
    X x2{ "2", "80", "FE02", "0713"};
    X x3{ "3", "180", "FE03", "0714"}; 
    X x4{ "4", "80", "FE04", "0715"};


    Insert(x1,&c); // Doesnt work.
    Insert(x2,&c); // Doesnt work.
    Insert(x3,&c); // Doesnt work.
    Insert(x4,&c); // Doesnt work.

    auto& indexByI3 = c.get<IndexByPanelID>();
    for(auto i = indexByI3.begin(); i != indexByI3.end(); i++)
    {
        X *x = *i;
        std::cout << x->name << '\n';
        std::cout << x->messageid << '\n';
        std::cout << x->panelid << '\n';
        std::cout << x->tid << '\n';
    }

int main()
{
    Container c;  // empty container
    X x1{ "1", "80", "FE01", "0712"};
    X x2{ "2", "80", "FE02", "0713"};
    X x3{ "3", "180", "FE03", "0714"}; 
    X x4{ "4", "80", "FE04", "0715"};
    // Insert some elements
    auto& indexByL = c.get<IndexByPanelID>(); 
    indexByL.insert(&x1); //works fine.
    indexByL.insert(&x2); //works fine.
    indexByL.insert(&x3); //works fine.
    indexByL.insert(&x4); //works fine.

    auto& indexByI3 = c.get<IndexByPanelID>();
    for(auto i = indexByI3.begin(); i != indexByI3.end(); i++)
    {
        X *x = *i;
        std::cout << x->name << '\n';
        std::cout << x->messageid << '\n';
        std::cout << x->panelid << '\n';
        std::cout << x->tid << '\n';
    }
}

输出第一个主要:

0715
80
4
FE04
0715
80
4
FE04
0715
80
4
FE04
0715
80
4
FE04

第二主线:

0712
80
1
FE01
0713
80
2
FE02
0714
180
3
FE03
0715
80
4
FE04

您没有提供工作代码。你过度使用指针。第一个错误使代码可以编译:

int Insert(X newframe, Container *Cont)

应该是

int Insert(X newframe, Container& c)

真正的问题是您存储的是指针,而不是框架。在 Insert 函数中插入的指针是悬空的(它们指向参数 frame,它在 Insert 的 return 之后消失了),所以行为是 Undefined.

最后,当插入新项目时,不需要通过额外的环跳到 select 一个特定的索引(除非你需要一个特定于索引的迭代器到新插入的元素.不过,你好像根本就没有return值)。

这是一个带有修复的简化版本:

Live On Compiler Explorer

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
#include <iomanip>
namespace bmi = boost::multi_index;

#include <string>
struct X { std::string panelid, messageid, tid, name; };

using Container = bmi::multi_index_container<
    X,
    bmi::indexed_by<                                   //
        bmi::hashed_non_unique<                        //
            bmi::tag<struct ByPanelID>,                //
            bmi::member<X, std::string, &X::panelid>   //
            >,                                         //
        bmi::hashed_non_unique<                        //
            bmi::tag<struct ByMessageID>,              //
            bmi::member<X, std::string, &X::messageid> //
            >,                                         //
        bmi::hashed_non_unique<                        //
            bmi::tag<struct ByTID>,                    //
            bmi::member<X, std::string, &X::tid>       //
            >>>;

void Insert(X newframe, Container &c) {
    c.insert(std::move(newframe));
}

int main()
{
    Container c;  // empty container

    Insert({ "1", "80",  "FE01", "0712"},c);
    Insert({ "2", "80",  "FE02", "0713"},c);
    Insert({ "3", "180", "FE03", "0714"},c);
    Insert({ "4", "80",  "FE04", "0715"},c);

    for (auto& [panelid, messageid, tid, name] : c.get<ByPanelID>()) {
        std::cout << std::quoted(name) << ' '      //
                  << std::quoted(messageid) << ' ' //
                  << std::quoted(panelid) << ' '   //
                  << std::quoted(tid) << '\n';
    }
}

版画

"0712" "80" "1" "FE01"
"0713" "80" "2" "FE02"
"0714" "180" "3" "FE03"
"0715" "80" "4" "FE04"

事实上,对于这个简单的演示,您可以做得更简单:https://godbolt.org/z/hbeeGd7ox