Проблема с вектором в C++

140
19 января 2020, 17:30

Есть вот такой класс Student.

class Student
{
public:
    Student(){}
    Student(const Student &student) {
        firstName = student.firstName;
        secondName = student.secondName;
        patronymic = student.patronymic;
        dateOfBirth = student.dateOfBirth;
        address = student.address;
        number = student.number;
        faculty = student.faculty;
        course = student.course;
    }
    ~Student()
    {
        delete firstName;
        delete secondName;
        delete patronymic;
        delete dateOfBirth;
        delete address;
        delete number;
        delete faculty;
        delete course;
    }
    void setFirstName(std::string *firstName) {
        this->firstName = firstName;
    }
    void setSecondName(std::string *secondName) {
        this->secondName = secondName;
    }
    void setPatronymic(std::string *patronymic) {
        this->patronymic = patronymic;
    }
    void setDateOfBirth(std::string *dateOfBirth) {
        this->dateOfBirth = dateOfBirth;
    }
    void setAddress(std::string *address) {
        this->address = address;
    }
    void setNumber(std::string *number) {
        this->number = number;
    }
    void setFaculty(std::string *faculty) {
        this->faculty = faculty;
    }
    void setCourse(std::string *course) {
        this->course = course;
    }
    std::string getFirstName() {
        return *firstName;
    }
    std::string getSecondName() {
        return *secondName;
    }
    std::string getPatronymic() {
        return *patronymic;
    }
    std::string getDateOfBirth() {
        return *dateOfBirth;
    }
    std::string getAddress() {
        return *address;
    }
    std::string getNumber() {
        return *number;
    }
    std::string getFaculty() {
        return *faculty;
    }
    std::string getCourse() {
        return *course;
    }
    std::string show() {
        std::string comma = ", ";
        return *secondName + comma + *firstName + comma + *patronymic +
               comma + *dateOfBirth + comma + *address + comma + *number + comma +
               *faculty + comma + *course + ". ";
    }

private:
    std::string *firstName = new std::string;
    std::string *secondName = new std::string;
    std::string *patronymic = new std::string;
    std::string *dateOfBirth = new std::string;
    std::string *address = new std::string;
    std::string *number = new std::string;
    std::string *faculty = new std::string;
    std::string *course = new std::string;

};

При создание вектора этого класса вот таким образом и вставкой в конец экземпляра этого класса, вылетает ошибка -1073741819;

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "Student.h"
using namespace std;
int main()
{
    vector<Student> vector;
    vector.push_back(Student());
}

Но вот таким образом всё отрабатывает нормально.

#include <fstream>
#include <string>
#include <vector>
#include "Student.h"
using namespace std;
int main()
{
    vector<Student*> vector;
    vector.push_back(new Student());
}

В чём причина такого поведения?

Answer 1

У вас полно полей типа

std::string *address = new std::string;
std::string *number = new std::string;

т.е. адреса, указывающие на некоторое место в памяти.

В деструкторе вы их удаляете.

Но ведь в конструкторе копирования вы копируете эти адреса:

Student(const Student &student) {
    ...
    address = student.address;
    number = student.number;

Значит, при удалении а оригинала, и копии, вы будете дважды удалять одну и ту же память.

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

Но вообще говоря, это не единственная ваша ошибка. Например, у вас нет оператора присваивания, в функциях типа

void setFaculty(std::string *faculty) { this->faculty = faculty; }

вы не освобождаете старую память (что ведет к утечкам).

Не вижу вообще ни малейшего смысла в ваших указателях на string - просто работайте со строками, будет проще и надежнее - не с

std::string *address = new std::string;
std::string *number = new std::string;

а с

std::string address;
std::string number;
Answer 2
  1. Конструктор копирования копирует указатели, а потом оба объекта их удаляют в деструкторе.
  2. Та же проблема с методами set*.
  3. В коде с указателями в векторе деструкторы студентов вообще не вызываются.
  4. В этом классе вообще нет смысла держать указатели, замени на нормальные строки.
READ ALSO
Discord JDA. Как удалять сообщения в Discord?

Discord JDA. Как удалять сообщения в Discord?

Столкнулся с такой проблемой: нужно удалить N сообщений на канале в дискордеКак это сделать?

110
Группировка изображений

Группировка изображений

какой алгоритм кластеризации и меру похожести для изображений подскажите или порекомендуете? какие этапы для этого нужно сделатьбуду благодарен...

125
Что быстрей String или UUID?

Что быстрей String или UUID?

Хотелось бы раз и навсегда выяснить, что лучше и целесообразнее использовать в виде ключа в хэш-коллекциях String или UUID?

143