【问题标题】:Custom string implementation, operator + overload memory allocation issue自定义字符串实现,运算符+重载内存分配问题
【发布时间】:2016-02-26 17:51:16
【问题描述】:

我正在尝试在 C++ 中创建自定义字符串实现,但我遇到了重载运算符“+”的问题。我想将新字符串附加到现有字符串,当我尝试分配一个新的扩展字符串时,调试器会分配大约 12 个字节。我无法控制分配,他只是忽略了变量“长度”。代码如下:

    class String 
{
private:
    char *ptrNiz;
public:

String(const char *niz = "")
    {
        ptrNiz = new char[strlen(niz)+1];

        strcpy_s(ptrNiz, strlen(niz)+1, niz);

        cout << "stvoren niz: " << ptrNiz << endl;
    }
    String(const String& refString)
    {
        ptrNiz = new char[strlen(refString.ptrNiz) + 1];
        strcpy_s(ptrNiz, strlen(refString.ptrNiz) + 1, refString.ptrNiz);
        cout << "Kopiran niz: " << ptrNiz << endl;
    }
    ~String()
    {
        cout << "Unisten objekt: " << ptrNiz << endl;
        delete[] ptrNiz;
    }

    int Length() const 
    {
        return strlen(ptrNiz);
    }
    int CharAt(int i) const
    {
        return ptrNiz[i];
    }
    void Ispisi()
    {
        cout << ptrNiz << endl;
    }

    operator char*()
    {
        return ptrNiz;
    }

    String operator+=(const const String& ref)
    { 
        const int const length = ref.Length() + this->Length() + 1;

        char *temp = new char[length]; // ignores length and allocates more space

        for (int i = 0; i < this->Length(); i++)
        {
            temp[i] = ptrNiz[i];
        }
        for (int j = 0; j < ref.Length(); j++)
        {
            temp[this->Length() + j] = ref.ptrNiz[j];
        }

        return String(temp);
    }

};

【问题讨论】:

  • 我建议你检查this binary arithmetic operator reference,它有一个重载+= 运算符的示例。现在尝试将其与您的进行比较,我认为您会发现您的操作员功能存在一些问题。该示例中提到的重要内容之一是它是一个 assignment,即对 this 的分配。从你的问题来看,我认为你混合了operator+和operator+=。
  • 你是否甚至终止了新的字符串?看起来你只是复制两个字符串并在最后留下一个垃圾字符。
  • 在你的描述中你说operator+,但在你的代码中你有operator+=。
  • 你好,运算符应该是+=,我们发现了一个问题,我没有在字符串末尾设置一个空数组'\0'。当然,我也会修复其余的代码错误。

标签: c++ operator-overloading


【解决方案1】:
char *temp = new char[length]; // ignores length and allocates more space

您的 C++ 实现在这里需要做的就是返回一个指向内存位置的指针,该内存位置有空间用于length 字节。不多也不少。允许在内部分配更多字节,即使您的代码不得尝试访问它们(否则行为未定义)。

动态内存分配的底层细节是一个实现问题,而不是您的代码关心的问题。

对于 C++ 实现可能使用额外字节来获取调试信息的情况,调试构建是一个很好的示例。事实上,这可能就是这里发生的事情。我想你正在使用 Visual C++。正如its documentation (CRT Debug Heap Details) 所说:

当您请求一个内存块时,调试堆管理器从 基堆比请求的内存块稍大和 返回指向该块的您的部分的指针。

[...]

调试堆例程分配的额外内存用于 簿记信息,用于链接调试内存块的指针 一起,并让数据两侧的小缓冲区捕获 覆盖分配的区域。

请注意,您的代码中还有许多其他严重错误。我决定暂时忽略它们,只回答了你提出的确切问题。

【讨论】:

    【解决方案2】:

    您分配了两次,一次在构造函数中,另一次在 operator+= 方法中。您也没有删除运算符函数中的指针,以免内存泄漏。要么使用智能指针,要么提供额外的构造函数参数来指定传入指针的所有权。

    【讨论】:

    • “要么使用智能指针,要么提供额外的构造函数参数来指定传入指针的所有权。” - 或者只使用std::string :)
    【解决方案3】:

    请在您的代码中添加以下行以使用NULL 终止字符串;

    String operator+=(const const String& ref)
    {
       // You code goes here
        temp[length - 1] = '\0';
        return String(temp);
    }
    

    这将按预期工作。

    希望这会有所帮助。

    【讨论】:

    • 虽然建议不错(我第一次看到;)),但这并不是问题的真正答案。
    • 嗨,我按照你说的做了,它有效。当然,我会修复指针问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多