What is the right way of implementing C++ setters in char array wrapper class?
I'm working on the class that simply contains a character array and it's size (length in bytes). At the moment, I want to overload '+' operand for this class (to implement concatenation). Constructors work fine. Objects are created and I can see their fields and values in the debugger. I'm stuck at the point where '+' is used (main(line 13)). Code compiles well, without even warnings, but as I run it, my program fails with "invalid pointer message". And I found where exactly that invalid pointer is. It is in '+' implementation (BufferArray.cpp, line 39). When i call SetBuffer, char array is assigned properly (I saw it's value 'qwasd' in the operator implementation scope), but right at the next line it's vanished when I call SetSize. I have no idea why.
What is wrong with my setters and how can I implement '+' operand in this case?
Thanks in advance.
Here's the code I work with:
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 */
Implementation is in the next file 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;
}
And the main function:
#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;
开发者_开发技巧}
in BufferArray::operator+, tempCharArray is a temporary buffer that will be destroyed when the function completes. There a basically two ways to handle this:
1/ allocate the temporary buffer with new[] in operator+, that way you'll make sure the buffer survives the call to operator+ but you'll either have a memory leak or require the caller to invoke delete[] later on, which is rather clumsy and error-prone
2/ or better yet, modify setBuffer so it does an internal copy of the buffer and add a call to delete[] in your own destructor :
BufferArray::~BufferArray() {
delete[] buffer;
}
void BufferArray::setBuffer(char *otherBuffer) {
buffer = new char[strlen(otherBuffer) + 1];
strcpy(buffer, otherBuffer);
}
Note that you'll have to modify the constructor so it also copies the input buffer (otherwise you'll have an illegal call to delete[] when the object is destroyed), and then you may want to overload the copy-constructor and assignment operator to prevent shallow copy which would result in double-deleting the buffer.
In actual production code, you'd want to use a managed pointer of some sort to avoid doing the delete yourself (e.g. std::vector or boost::shared_array), but for homework the above solution should be fine.
On a side note, don't forget to add +1 when using strlen to determine the size of your buffer ;)
You need to use new
to create these char arrays, otherwise the temporaries (like tempBA) are destroyed when you exit the scope.
void BufferArray::SetBuffer(char* buf)
{
buffer = new char[strlen(buf)+1]; //edit, my size param wasn't necessary
strcpy(buffer,buf);
}
精彩评论