#c #operator-overloading #setter
#c #перегрузка оператора #установщик
Вопрос:
Я работаю над классом, который просто содержит массив символов и его размер (длина в байтах). На данный момент я хочу перегрузить операнд ‘ ‘ для этого класса (для реализации конкатенации). Конструкторы работают нормально. Объекты созданы, и я могу видеть их поля и значения в отладчике. Я застрял в точке, где используется ‘ ‘ (main (строка 13)). Код компилируется хорошо, даже без предупреждений, но когда я его запускаю, моя программа завершается сбоем с «сообщением о недопустимом указателе». И я нашел, где именно находится этот недопустимый указатель. Это в реализации ‘ ‘ (BufferArray.cpp, строка 39). Когда я вызываю SetBuffer, массиву символов присваивается правильное значение (я видел его значение ‘qwasd’ в области реализации оператора), но прямо в следующей строке оно исчезает, когда я вызываю setSize . Я понятия не имею, почему.
Что не так с моими установщиками и как я могу реализовать операнд ‘ ‘ в этом случае?
Заранее спасибо.
Вот код, с которым я работаю:
BufferArray.h:
#include <string.h>
#include <stdio.h>
#ifndef BUFFERARRAY_H
#define BUFFERARRAY_H
class BufferArray {
public:
BufferArray(char* reservedPlace);
BufferArray();
void SetSize(int sz);
int GetSize();
void SetBuffer(char* buf);
char* GetBuffer();
BufferArray operator (BufferArray bArr) const;
virtual ~BufferArray();
private:
int size;
char *buffer;
};
#endif /* BUFFERARRAY_H */
Реализация находится в следующем файле BufferArray.cpp:
#include "BufferArray.h"
// Constructors.
BufferArray::BufferArray(){
size = 0;
strcpy(buffer, "");
}
BufferArray::BufferArray(char* reservedPlace) {
size = strlen(reservedPlace);
buffer = reservedPlace;
}
// Getters and setters.
void BufferArray::SetSize(int sz)
{
size = sz;
}
int BufferArray::GetSize()
{
return size;
}
void BufferArray::SetBuffer(char* buf)
{
buffer = buf;
}
char* BufferArray::GetBuffer()
{
return buffer;
}
// Operator .
BufferArray BufferArray::operator (BufferArray bArr) const
{
char tempCharArray[strlen(buffer) strlen(bArr.GetBuffer())];
strcpy(tempCharArray, buffer);
strcat(tempCharArray, bArr.GetBuffer());
BufferArray tempBA;
tempBA.SetBuffer(tempCharArray);
tempBA.SetSize(strlen(bArr.GetBuffer()) strlen(buffer)); // Vanishes buffer field.
printf("%d",tempBA.GetSize());
return tempBA;
}
// Destructor.
BufferArray::~BufferArray() {
// Destroy the pointer.
delete [] buffer;
}
И функция main:
#include <cstdlib>
#include <iostream>
#include "BufferArray.h"
using namespace std;
int main(int argc, char** argv) {
BufferArray ba1;
char tmp1[3] = "qw";
char tmp2[4] = "asd";
ba1.SetSize(strlen(tmp1));
ba1.SetBuffer(tmp1);
BufferArray ba2(tmp2);
BufferArray ba3 = ba1 ba2; // Runtime error is here.
cout << ba3.GetBuffer() << endl;
return 0;
}
Ответ №1:
в BufferArray::operator tempCharArray является временным буфером, который будет уничтожен при завершении функции. В основном существует два способа справиться с этим:
1 / выделите временный буфер с помощью new[] в operator , таким образом, вы убедитесь, что буфер выдержит вызов operator , но у вас либо возникнет утечка памяти, либо потребуется, чтобы вызывающий вызывал delete[] позже, что довольно неуклюже и подвержено ошибкам
2 / или, что еще лучше, измените setBuffer, чтобы он выполнял внутреннюю копию буфера, и добавьте вызов delete[] в свой собственный деструктор :
BufferArray::~BufferArray() {
delete[] buffer;
}
void BufferArray::setBuffer(char *otherBuffer) {
buffer = new char[strlen(otherBuffer) 1];
strcpy(buffer, otherBuffer);
}
Обратите внимание, что вам придется изменить конструктор, чтобы он также копировал входной буфер (в противном случае у вас будет незаконный вызов delete[] при уничтожении объекта), а затем вы можете захотеть перегрузить конструктор копирования и оператор присваивания, чтобы предотвратить мелкое копирование, которое привело бы к двойному удалению буфера.
В реальном производственном коде вы хотели бы использовать какой-либо управляемый указатель, чтобы избежать самостоятельного удаления (например, std::vector или boost::shared_array), но для домашней работы приведенное выше решение должно подойти.
Кстати, не забудьте добавить 1 при использовании strlen для определения размера вашего буфера 😉
Комментарии:
1. Я попытался посмотреть, что возвращает strlen (buf), когда ‘buf’ передается в качестве параметра ввода, и обнаружил, что он работает должным образом (он возвращает 5). Спасибо за ответы! Сейчас я пытаюсь исправить свой класс. Я приму соответствующий ответ после того, как он заработает.
2. Это работает! В дополнение к изменениям в коде установщика и конструктора, где для создания массивов символов использовалось ключевое слово ‘new’, мне пришлось динамически выделять BufferArray tempBA следующим образом: BufferArray *tempBA = new BufferArray(tempCharArray); И затем я возвращаю *tempBA, а не tempBA.
Ответ №2:
Вам нужно использовать new
для создания этих массивов символов, иначе временные файлы (например, tempBA) будут уничтожены при выходе из области видимости.
void BufferArray::SetBuffer(char* buf)
{
buffer = new char[strlen(buf) 1]; //edit, my size param wasn't necessary
strcpy(buffer,buf);
}