В настоящее время я работаю над ADT с именем Text и перегружаю оператор присваивания. Когда я тестирую оператора, вот так: assignText = alpha
все выводит нормально. Тем не менее, когда я делаю assignText = assignText
затем вместо него выводятся две сплошные полосы.
assignText объявлен как текстовый объект.
Мой перегруженный оператор присваивания выглядит следующим образом:
void Text::operator= (const Text& other) {
bufferSize = other.getLength();
buffer = new char[bufferSize];
buffer = other.buffer;
}
куда int bufferSize
а также char *buffer
Любые советы или предложения будут с благодарностью. Если что-то еще нужно, просто дайте мне знать.
Другие ответы уже указали на различные проблемы с реализацией вашего оператора. Здесь я постараюсь понять, что у вас происходит, т.е. Зачем код ведет себя так, как вы наблюдаете. Если this == &other
во время самоназначения вы берете текущую длину в качестве размера нового буфера. Этот новый буфер не инициализирован, поэтому в этот момент он может содержать случайные байты. Последнее назначение не разрешается в случае самоопределения. Подводя итог:
void Text::operator= (const Text& other) {
bufferSize = other.getLength(); // Take length from current object
buffer = new char[bufferSize]; // Create new buffer, old buffer turns into a memory leak
buffer = other.buffer; // No-op as both are the same variable
}
Так что это говорит вам о том, что вы получите буфер текущего размера, но с неопределенным содержимым. В вашем случае это неопределенное содержимое представляет вертикальные полосы, которые вы упоминаете.
Чтобы решить эту проблему, обязательно исправьте оператор присваивания на основе предложений из других ответов и комментариев.
Это утечка памяти. Вы назначаете два разных указателя buffer
,
buffer = new char[bufferSize];
buffer = other.buffer;
относительно эта проблема под рукой, это описано в C ++ FAQ: «Почему я должен беспокоиться о« самостоятельном назначении »?». Часто рекомендуется сначала прочитать FAQ. Или, по крайней мере, снять это.
Когда вам абсолютно необходимо реализовать оператор присваивания копии, обычно идиома копирования и замены будет достаточно хороша. Это также исключение безопасно. Идет так:
void swapWith( MyType& other ) throw()
{
// swap them members
}
void operator=( MyType other )
{
swapWith( other );
}
Здесь конструктор копирования создает формальную копию аргумента, и там происходит любое исключение, так что конструктор копирования также централизует очистку в случае сбоя копирования. После этого содержимое двух объектов меняется местами, и деструктор объекта копирования заботится об очистке того, что было внутренним материалом этого объекта. void
Тип результата еще не является общепринятым, но, как я вижу, не разумно тратить и код, и время на поддержку выражений с побочными эффектами, которые являются злом.
Теперь ваша очередь можно избежать всего этого, просто с помощью std::vector
для вашего буфера.
Вот что я рекомендую, действительно простое решение: используйте std::vector
,
Это потому, что ваш оператор присваивания в основном небезопасен. Вам нужно сломать старое государство как прошлой шаг. Рассматривать
Text& Text::operator= (const Text& other) {
auto new_buffer = new char[other.bufferSize];
std::copy(other.buffer, other.buffer + other.bufferSize, new_buffer);
// Now consider whether or not you need to deallocate the old buffer.
// Then set the new buffer.
buffer = new_buffer;
bufferSize = other.bufferSize;
return *this;
}
Это гарантирует, что в случае возникновения каких-либо проблем гарантируется, что Text
Объект всегда действителен и, в качестве бонуса, безопасен для самостоятельного назначения. Все хорошо написанные операторы присваивания являются безопасными для присваивания.
Это часто связано с копированием и обменом, которое копирует, а затем обменивает, гарантируя безопасность.
Этот кусок кода будет работать отлично
Text& Text::operator=(const Text& other)
{
if(this == &other) /* checks for self assignment */
return *this;
if(NULL == other.buffer)
return *this;
if(NULL != buffer) /* assuming buffer=NULL in constructor */
{
delete [] buffer;
buffer = NULL;
}
bufferSize = other.getLength();
buffer = new char[bufferSize+1];
memset(buffer, 0, bufferSize+1);
memcpy(buffer, other.buffer, bufferSize);
return *this;
}
Попробуй это..
После некоторой мысли и обзора, я думаю, что понял. Учитывая, что мне нужно написать функцию void, продиктованную заголовочным файлом, из которой я должен построить свою реализацию. Я принял во внимание комментарии Дрю Дормана, MvG, а также других, и придумал следующее:
void Text::operator= (const Text &other)
{
if (this != &other) // takes care of self-assignment
{
delete [] buffer; // delete the old buffer
bufferSize = other.bufferSize; // assign size variable
buffer = new char[bufferSize + 1]; // create new buffer
strcpy(buffer, other.buffer); // copy array
}
}
Это работает, и я считаю, что это без утечки памяти.