实施 C++ 的正确方法是什么? char 数组包装类中的设置器?

发布于 2024-11-09 11:28:36 字数 2426 浏览 5 评论 0 原文

我正在研究仅包含字符数组及其大小(以字节为单位的长度)的类。目前,我想重载此类的“+”操作数(以实现串联)。构造函数工作正常。对象已创建,我可以在调试器中看到它们的字段和值。我被困在使用“+”的地方(主线(第13行))。代码编译得很好,甚至没有警告,但是当我运行它时,我的程序失败并显示“无效指针消息”。我找到了那个无效指针到底在哪里。它位于“+”实现中(BufferArray.cpp,第 39 行)。当我调用 SetBuffer 时,char 数组被正确分配(我在运算符实现范围中看到它的值“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;
}

ma​​in 函数中:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

所有深爱都是秘密 2024-11-16 11:28:36

在 BufferArray::operator+ 中,tempCharArray 是一个临时缓冲区,函数完成时将被销毁。基本上有两种方法来处理这个问题:

1/在operator+中使用new[]分配临时缓冲区,这样你就可以确保缓冲区在对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),但对于家庭作业,上述解决方案应该没问题。

顺便说一句,当使用 strlen 确定缓冲区的大小时,不要忘记添加 +1 ;)

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 ;)

友谊不毕业 2024-11-16 11:28:36

您需要使用 new 来创建这些 char 数组,否则当您退出作用域时,临时数组(如 tempBA)将被销毁。

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

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文