Оператор присваивания копированием C++ с динамически выделенным вектором

Вопрос или проблема

При попытке создать глубокую копию динамически выделенного вектора, копируется только первый элемент вектора, остальные игнорируются. Что я упустил?

Vector& Vector::operator=(const Vector& v) {
    cout << "копирование начато " << endl;
    if (this != &v) {
        delete data_ptr;
        data_ptr = new int;
        *data_ptr = *(v.data_ptr);
        n_elems = v.n_elems;
        capacity = v.capacity;
   }
   return *this;
}

Вывод:
Vector1: 1, 2, 3, 4
Vector2: 1, 13041856, 600866540, 251678015

Ответ или решение

Оператор присваивания копирования в C++ для динамически выделенного вектора: проблемы и решения

При реализации оператора присваивания копирования для класса, который использует динамически выделенные массивы или векторы, важно обеспечить правильное копирование данных. В вашем случае возникает проблема с тем, что копируется только первый элемент вектора. Давайте рассмотрим код и выявим, что именно идет не так.

Проблемы в коде

В приведенном вами коде присутствует ошибка в логике копирования данных. Вместо того чтобы создать глубокую копию всего динамически выделенного массива, вы создаете лишь одну переменную, что приводит к тому, что не все элементы исходного вектора копируются в новый. Давайте проанализируем строки вашего кода по порядку:

delete data_ptr;
data_ptr = new int;
*data_ptr = *(v.data_ptr);
  1. Удаление указателя: Вы корректно удаляете старый массив, ссылающийся на data_ptr. Это необходимо для предотвращения утечки памяти.
  2. Выделение памяти для одного элемента: В следующей строке вы выделяете память только для одного элемента типа int, что, очевидно, является причиной проблемы. Вы должны выделить память для всего массива, а не только для первого элемента.
  3. Копирование первого элемента: Также после выделения вы копируете лишь первое значение из вектора другого экземпляра v, что объясняет, почему вы видите только один искаженный элемент в вашем выходном результате.

Решение проблемы

Чтобы исправить код, вам необходимо сделать следующее:

  1. Выделить память для всего массива, в соответствии с количеством элементов в векторе.
  2. Использовать цикл для копирования каждого элемента из массива v.

Вот исправленный код оператора присваивания копирования:

Vector& Vector::operator=(const Vector& v) {
    cout << "copy started " << endl;
    if (this != &v) { // Проверка самоприсваивания
        delete[] data_ptr; // Удаляем старый массив
        n_elems = v.n_elems; // Устанавливаем количество элементов
        capacity = v.capacity; // Устанавливаем емкость
        data_ptr = new int[n_elems]; // Выделяем память под весь массив
        for (int i = 0; i < n_elems; ++i) { // Копируем каждый элемент
            data_ptr[i] = v.data_ptr[i];
        }
    }
    return *this; // Возврат ссылки на текущий объект
}

Пояснения к исправлениям:

  • Массив с помощью new[]: Мы выделяем память для массива data_ptr с учетом всех элементов.
  • Цикл копирования: Используя цикл, мы проходим по всем элементам массива и копируем их из объекта v в текущий объект.
  • Проверка самоприсваивания: Мы также оставляем проверку if (this != &v), чтобы избежать удаления и повторного выделения памяти, если объект присваивается сам себе.

Заключение

Эти изменения позволят вашему оператору присваивания копирования корректно создавать глубокую копию динамически выделенного вектора, что устранит проблему искаженных данных. Пользуясь этим подходом, вы улучшите надежность вашего кода и избежите утечек памяти, что является критически важным для приложений, использующих динамическую память.

Оцените материал
Добавить комментарий

Капча загружается...