Указатель меняет значение после выхода из конструктора - PullRequest
0 голосов
/ 16 марта 2020

По какой-то причине всякий раз, когда она переназначает строку в качестве другого const char *, возникает ошибка После того, как он создает новый буфер в строке с предыдущим буфером, когда он существует, конструктор буфер меняет значение без причины. Я использую кучу памяти, поэтому она не должна зависеть от объема.

#include <iostream>

class String {
private:
    char* buffer;
    unsigned int size;
public:
    String(const char* string) {
        size = strlen(string);
        buffer = new char[size + 1];
        memcpy(buffer, string, size + 1);
        buffer[size] = 0;
    }
    String(const String& other) {
        memcpy(this, new String(other.buffer), sizeof(String));
    }
    ~String() {
        delete buffer;
    }

    friend std::ostream& operator<<(std::ostream& stream, const String& str);

    String operator+(const String& other) {
        unsigned int nSize = this->size + other.size;
        char* nBuffer = new char[nSize + 1];
        memcpy(nBuffer, this->buffer, nSize + 1);
        strcat(nBuffer, other.buffer);
        nBuffer[nSize] = 0;

        return String(nBuffer);
    }

    void operator+=(const String& other) {
        unsigned int nSize = this->size + other.size;
        char* nBuffer = new char[nSize + 1];
        memcpy(nBuffer, this->buffer, nSize + 1);
        strcat(nBuffer, other.buffer);
        nBuffer[nSize] = 0;

        this->~String();
        memcpy(this, new String(nBuffer), sizeof(String));
    }
};

std::ostream& operator<<(std::ostream& stream, const String& str) {
    stream << str.buffer;
    return stream;
}

int main() {
    String test1 = "Hello";
    test1 = "there";

    std::cout << test1 << std::endl;
}

1 Ответ

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

test1 = "there" совпадает с test1 = String("there"), потому что строка "there" должна быть преобразована в String. Оператор назначения по умолчанию работает, назначая все элементы с правой стороны элементам с левой стороны. Он делает поверхностную копию всех элементов, поэтому ваши строки на самом деле не дублируются, а оба указателя buffer в test1 и String("there") указывают на одну и ту же область памяти, в которой хранится строка "there".

В конце назначения объект String("there") должен быть уничтожен, поэтому он вызывает деструктор, который delete хранит память, на которую указывает его buffer. В конце метода main() то же самое происходит с test1, только когда он попадает туда, он обнаруживает, что память уже была удалена, вызывая ошибку времени выполнения.

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

String& operator=(String const& other) {
  delete[] buffer;
  buffer = new char[other.size + 1];
  strcpy(buffer, other.buffer);
  size = other.size;
  return *this;
}

Теперь присвоение test1 выделит полностью отдельное пространство памяти для хранения строки.

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