Алгоритм for_each приводит к тому, что значение basic_string :: _ M_construct недопустимо в C ++ - PullRequest
0 голосов
/ 20 февраля 2019

В проекте по изучению C ++ я создал программное обеспечение, составленное из двух простых классов (Дом и Люди).Люди имеют для конструктора:

// CONSTRUCTOR
    People(): name("NoName"), first_name("NoFirstName"), age(0){}
    People(std::string n, std::string fn, int a) : name(n), first_name(fn), age(a){}

И у дома есть:

// CONSTRUCTOR
    Home(): adresse("NoName"){}
    Home(std::string addr): adresse(addr){}

В моем программном обеспечении дом имеет вектор людей, в который мы можем добавить резидента или удалить резидента.

Моя ошибка возникает при попытке удалить резидента в доме или при попытке распечатать дом.

Вот код «removeResident»:

void Home::removeHabitant(People const &p)
{
    this->getHabitant().erase(std::remove(this->getHabitant().begin(), this->getHabitant().end(), p));
}

Вот код «оператора <<»: </p>

std::ostream & operator<<(std::ostream & out, Home const &h)
{
out << h.getAddr() << "\n"; //OK 
if(h.getHabitant().size() > 0) // OK
{
    try
    {
        std::for_each(h.getHabitant().begin(), h.getHabitant().end(), [&out](People const pe){
            out << pe << "\n";

        }); // ERROR
    }
    catch(People p)
    {
        std::cout << "Exception à l'element : " << p << std::endl;
    }

}
else // OK
{
    out << "Aucun habitant !"; // OK
}
return out ;  // OK }

Вот вывод моего программного обеспечения:

clang++ -Wall -std=c++11 -c -o obj/main.o src/main.cpp -I include
clang++ -Wall -std=c++11 -c -o obj/People.o src/People.cpp -I include
clang++ -Wall -std=c++11 -c -o obj/Home.o src/Home.cpp -I include
clang++ -Wall -std=c++11 -o bin/main obj/main.o obj/People.o obj/Home.o
./bin/main
Peoples's destructor
( NoFirstName - NoName - 0 )
10 rue des Brouettes rouge
Peoples's destructor
Peoples's destructor
( Erwan - AUBRY - 21 )
Peoples's destructor
( Roger - DURAND - 20 )
Peoples's destructor
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
makefile:6: recipe for target 'compile' failed
make: *** [compile] Aborted

Вот основной файл:

#include <Home.hpp>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
    People erwan("AUBRY", "Erwan", 21);
    People roger("DURAND", "Roger", 20);
    People noName;

    // vector<People> lsPeople;
    // lsPeople.push_back(erwan);
    // lsPeople.push_back(roger);

    // copy(lsPeople.begin(), lsPeople.end(), ostream_iterator<People>(cout, "|"));

    Home home1("10 rue des Brouettes rouge");
    home1.addHabitant(erwan);
    home1.addHabitant(roger);

    cout << noName << endl;
    cout << home1 << endl;

    // cout << home1[0] << endl;
    // home1.removeHabitant(roger);
    // cout << home1[0] << endl;

    return 0;
}

ПослеНесколько исследований, я думаю, что это причина домашнего класса, так вот код домашнего .hpp:

#ifndef HOME_INCLUDED
#define HOME_INCLUDED

#include <People.hpp>
#include <vector>

class Home
{
    private:
        std::string adresse;
        std::vector<People> habitant;

    public:
    // CONSTRUCTOR
        Home(): adresse("NoName"){}
        Home(std::string addr): adresse(addr){}

    // DESTRUCTOR
        ~Home(){std::cout << "Home's destructor" << std::endl;}

    // GETTER
        std::string getAddr() const{return this->adresse;}
        std::vector<People> getHabitant() const{return this->habitant;}

    // SETTER
        void setAddr(std::string const val){this->adresse = val;}
        void addHabitant(People const &p){this->habitant.push_back(p);}
        void removeHabitant(People const &p);

    // OPERATOR
        People & operator[](unsigned int const val){return this->habitant[val];}
};

std::ostream & operator<<(std::ostream & out, Home const &h);

#endif

Надеюсь, у вас есть какие-либо идеи для моих проблем.

PS: извинитеза мой английский, и извините, если я сделал что-то плохое, я новичок в поиске помощи в StackOverflow

1 Ответ

0 голосов
/ 20 февраля 2019

Как и замечает molbdnilo в замечании, в std::ostream & operator<<(std::ostream & out, Home const &h) вы выполняете итерацию

    std::for_each(h.getHabitant().begin(), h.getHabitant().end(), [&out](People const pe){

, которая предполагает, что h.getHabitant().begin() и h.getHabitant().end() являются итераторами для того же векторано

std::vector<People> getHabitant() const{return this->habitant;}

каждый раз возвращает новую копию вектора.

Если вы не хотите изменять getHabitant для возврата константыссылка на обитатель вы должны запомнить вектор, по которому вы выполняете итерацию.

std::vector<People> v = h.getHabitant();
std::for_each(v.begin(), v.end(), [&out](People const pe){

, но я призываю вас изменить getHabitant() на

const std::vector<People> & getHabitant() const {return this->habitant;}
...