Ошибка с памятью в перегрузке оператора

204
26 ноября 2016, 19:07

Есть вот такая перегрузка оператора ++ (постфиксная).

В this'е хранятся:

s="first"
length=5

Вот сам код:

String& String::operator++(int i)
{
    int n = this->length + 1;
    char* tmp = new char[n + 1];
    for (int i = 0; i < this->length; i++)
        tmp[i] = this->s[i];
    tmp[n - 1] = tmp[n - 2];
    tmp[n] = '\0';
    this->length = n;
    delete[] this->s;
    this->s = tmp;
    return *this;
}

На delete вылетает ошибка записи памяти.

Answer 1

Ну вообще, постфиксный инкремент по логике должен возвращать старое значение (строки), которое на самом деле должно являться копией. Больше не вижу ошибок в коде, но вылетать на delete может из-за того, как вы выделили s. Если она указывает на read-only memory, то это вполне логично.

Т.е. если начальное значение у вас присваивается как this->s = "blabla", а не создается новый массив char и в него копируется ваша read-only строка "blabla"

Answer 2

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

Что касается самого оператора, то обычно постинкрементный оператор возвращает новый временный объект, равный исходному до его изменения, и изменяет исходный. То есть его объявление выглядит в общем случае как

T operator ++( int );

или

const T operator ++( int );

Что касается вашего класса String, то если исходная строка пустая, то она не изменяется, так как в строке еще нет символов, чтобы использовать последний из них в качестве символа-заполнителя (Другой подход - это использовать в качестве заполнителя символ пробела).

С учетом сказанного оператор может выглядеть следующим образом

String operator ++( int )
{
    String dsn( *this );
    if ( this->length != 0 )
    {
        size_t n  = length + 1;
        char *tmp = new char[ n + 1 ];
        std::memcpy( tmp, this->s, this->length  );
        tmp[ length ] = tmp[ length - 1 ];
        tmp[n] = '\0';
        delete [] s;
        this->s = tmp;
        this->length = n;
    }
    return dsn;
}
READ ALSO
Как нарисовать в терминале линию?

Как нарисовать в терминале линию?

Мне нужно нарисовать 10 линийИз одной точки по одной линии в 10 других точек

272
Как реализовано разыменовывание указателя в C/C++?

Как реализовано разыменовывание указателя в C/C++?

Почему код int* p = &(*(&n)) корректно работает? Я, представляя себя компилятором, воспроизвожу код так:

249
Как получить результат SQL запроса?

Как получить результат SQL запроса?

выполняю вот такой запрос

227