Шаблон класса не работает с std :: string или объектом класса - PullRequest
0 голосов
/ 20 марта 2020

Я новичок в шаблонах C ++, и я изо всех сил пытался понять, почему функция append (), которую я реализовал для моего шаблона класса DynamicVector:

template<class EntityType>
void DynamicVector<EntityType>::append(const EntityType newEntity)
{
    if (this->size == this->capacity) {
        resize();
    }

    this->size += 1;
    this->data[this->size - 1] = newEntity;
}

не работает для каждого типа данных .

Создание и добавление нового элемента к динамическому c вектору int или char работает просто отлично, но когда дело доходит до std :: string или объекта класса, даже если объявление работает все в порядке (т. е. DynamicVector<std::string> test_dynamicVectorString или DynamicVector<MyClassObject> test_dynamicVectorMyClassObject), когда я пытаюсь добавить элемент к вектору:

DynamicVector<std::string> test_dynamicVector;
test_dynamicVector.append("asdasd");

нарушается доступ:

Исключение выдается в 0x6ED640C9 (vcruntime140d.dll) в DynVect.exe: 0xC0000005: Место записи нарушения прав доступа 0x0D3539A8.

У меня есть динамически размещенный массив внутри класса DynamicVector (EntityType* data = new EntityType[capacity];), где предполагается, что добавленные элементы чтобы сохранить, и на самом деле правильно хранятся, когда EntityType имеет тип int или char.

Но когда я пытаюсь сохранить строки, отладить и войти в функцию append (), на моих Авто появляется значение data:

0x0146539 Ошибка чтения символов строки>. <</p>

Фактически, то же самое значение появляется, даже когда я вхожу в конструктор и data инициализируется в списке инициализации члена:

template<class EntityType>
DynamicVector<EntityType>::DynamicVector() : size{ 0 }, capacity{ 1 }, data{ new EntityType[capacity] }
{
}

Это код класса DynamicVector.

DynamicVector.h

#pragma once

#include "ErrorMessages.h"


template <class EntityType>
class DynamicVector
{

public:
    DynamicVector();
    DynamicVector(const DynamicVector& original_dynamicVector);
    ~DynamicVector();

    void append(const EntityType newEntity);
    void erase(unsigned int indexToRemove);
    void clear();
    size_t get_size();
    EntityType& operator[](unsigned int index);
    DynamicVector& operator=(const DynamicVector& source);

private:
    const int GROWTH_RATE{ 2 };

    EntityType* data = new EntityType[capacity];
    size_t capacity;
    size_t size;

    void resize();
    bool validIndex(int index);
};

/// Contstructor
template<class EntityType>
DynamicVector<EntityType>::DynamicVector() : size{ 0 }, capacity{ 1 }, data{ new EntityType[capacity] }
{
}

/// Copy constructor
template<class EntityType>
DynamicVector<EntityType>::DynamicVector(const DynamicVector& original_dynamicVector)
{
    this->capacity = original_dynamicVector.capacity;
    this->size = original_dynamicVector.size;

    this->data = new EntityType[this->capacity];
    for (unsigned int i = 0; i < this->size; ++i) {
        this->data[i] = original_dynamicVector.data[i];
    }
}

/// Destructor
template<class EntityType>
DynamicVector<EntityType>::~DynamicVector()
{
}


/// <summary>
/// Appends the specified new entity to the dynamic vector
/// </summary>
/// <param name="newEntity">The new entity.</param>
template<class EntityType>
void DynamicVector<EntityType>::append(const EntityType newEntity)
{
    if (this->size == this->capacity) {
        resize();
    }

    this->size += 1;
    this->data[this->size - 1] = newEntity;
}


/// <summary>
/// Resizes the dynamic vector, when the capacity gets filled.
/// </summary>
template<class EntityType>
void DynamicVector<EntityType>::resize()
{
    EntityType* resizedSpace{ new EntityType[this->capacity *= GROWTH_RATE] };

    for (int i = 0; i < this->size; ++i) {
        resizedSpace[i] = this->data[i];
    }

    // delete[] this->data;
    this->data = resizedSpace;
}

Ответы [ 2 ]

1 голос
/ 20 марта 2020

У вас есть две проблемы, которые приводят к неопределенному поведению (и по той же причине неинициализированные переменные).

Первая и наиболее очевидная проблема - эти две строки в определении класса :

EntityType* data = new EntityType[capacity];
size_t capacity;

Здесь вы инициализируете data с помощью неинициализированной переменной-члена capacity. Использование capacity, когда оно неинициализировано, приведет к неопределенному поведению .

Так как вы инициализируете capacity и data в конструкторе, вам не требуется встроенная инициализация data.


Вторая проблема - это порядок инициализации в конструкторе.

Переменные-члены в списке инициализатора конструктора будут инициализированы в порядке объявления в класс, а не порядок в списке инициализатора конструктора.

Поскольку вы объявляете переменные-члены в порядке

EntityType* data;
size_t capacity;

член capacity будет неинициализированным когда вы используете его для инициализации data. Это также приводит к неопределенному поведению .

Вам необходимо изменить порядок объявлений на

size_t capacity;
EntityType* data;

С этой ссылки на порядок инициализации :

... non-stati c члены данных инициализируются в порядке объявления в определении класса .

[Выделение шахты ]

0 голосов
/ 20 марта 2020

EntityType* data = new EntityType[capacity]; в объявлении класса? Единственная причина, по которой это не утечка памяти, заключается в том, что это неопределенное поведение; емкость не инициализирована.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...