Как правильно реализовать сеттеры C ++ в классе-оболочке массива char? - PullRequest
2 голосов
/ 22 мая 2011

Я работаю над классом, который просто содержит массив символов и его размер (длина в байтах). В данный момент я хочу перегрузить операнд '+' для этого класса (для реализации конкатенации). Конструкторы работают нормально. Объекты созданы, и я вижу их поля и значения в отладчике. Я застрял в точке, где используется «+» (основной (строка 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;
}

И основная функция:

#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;
}

Ответы [ 2 ]

4 голосов
/ 22 мая 2011

в BufferArray :: operator +, tempCharArray - это временный буфер, который будет уничтожен после завершения функции.Существуют два основных способа решения этой проблемы:

1 / выделение временного буфера с помощью new [] в operator +, таким образом вы будете уверены, что буфер выдержит вызов оператора operator +, но у вас либо будет памятьутечь или потребовать, чтобы вызывающая сторона позже вызывала delete [], что довольно неуклюже и подвержено ошибкам

2 / или еще лучше, измените setBuffer, чтобы он делал внутреннюю копию буфера, и добавьте вызов для удаления[] в вашем собственном деструкторе:

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 голос
/ 22 мая 2011

Вам необходимо использовать new для создания этих массивов символов, в противном случае временные файлы (например, tempBA) будут уничтожены при выходе из области действия.

void BufferArray::SetBuffer(char* buf)
{
   buffer = new char[strlen(buf)+1]; //edit, my size param wasn't necessary
   strcpy(buffer,buf);
}
...