Home > Mobile >  How do I store the tmp object in a map, to acess the object outside of it's creation context
How do I store the tmp object in a map, to acess the object outside of it's creation context

Time:05-22

I am relatively new to C . I tried to break down the problem.

All code is also here: https://onlinegdb.com/wAmLAONkF (can be executed)

Basically, I have a function where temp objects are created. The objects are pushed to a std::vector:

vector<Student> GetStudents(int some_params)
{
    vector<Student> students;
    //logic where students are returned 
    Student s1 { "John", 42 };
    Student s2 { "Bill", 12 };
    students.push_back(s1);
    students.push_back(s2);
    
    return students;
}

To maintain the objects, they are stored outside in a std::map.

The map stores each Student by pointer in a vector<Student*> (it has to be vector<Student*>!):

map<int, vector<Student*>> m {};
    
{ //start of new context, other class context in another file, map is passed by reference
    int some_params = 5;
    vector<Student> students = GetStudents(some_params); 

To store them in the map, I copy references into a new vector:

    vector<Student*> tmpV;
    for(auto & student : students)
        tmpV.push_back( &student);

    //store them in the map
    m.emplace(some_params, tmpV);

}//leave context

//data loss - Students are lost 

I do know, that the problem is because the pointers to the objects are stored in a local vector. After I leave the context, the pointers do not point somewhere valid.

But how can I solve this?

CodePudding user response:

The vector<Student> returned by GetStudents() needs to be stored in a variable that is in the same scope as (or in a higher scope than) the std::map that refers to its Students, eg:

map<int, vector<Student*>> m;
vector<Student> students; // <-- move it up here!

{ //start of new context

    int some_params = 5;
    students = GetStudents(some_params); 

    vector<Student*> tmpV;
    for(auto & student : students)
        tmpV.push_back( &student);

    //store them in the map
    m.emplace(some_params, tmpV);

} //leave context

// no data loss - Students are valid!

Otherwise, GetStudents() will have to return a vector<Student*> instead, where each Student has been created dynamic via new, and then destroyed via delete after the map is done using them:

vector<Student*> GetStudents(int some_params)
{
    vector<Student*> students;
    //logic where students are returned 
    students.push_back(new Student{ "John", 42 });
    students.push_back(new Student{ "Bill", 12 });
    
    return students;
}

...

map<int, vector<Student*>> m;

{ //start of new context

    int some_params = 5;
    vector<Student*> students = GetStudents(some_params); 

    //store them in the map
    m.emplace(some_params, students);

} //leave context

// no data loss - Students are valid!

...

for(auto &entry : m) {
    for (auto *student : entry.second) {
        delete student;
    }
}

Ideally, your map should store either vector<Student> or vector<unique_ptr<Student>>, but your requirement of "it has to be vector<Student*>!" prevents that.

  • Related