【问题标题】:Rewriting += Operator C++重写 += 运算符 C++
【发布时间】:2011-12-06 03:36:05
【问题描述】:

更新:为 str1 的新数据分配内存。仍然记忆错误。

我正在尝试为我创建的字符串类重写 += 方法。

Class mystring{

public:
    friend void operator+=(mystring& str1, const mystring& str2){
        mystring temp;

        delete[] temp.data;
        temp.length = str1.length + str2.length;
        temp.data = new char[temp.length + 1];

        strcpy(temp.data, str1.data);
        strcat(temp.data, str2.data);

        delete[] str1.data;
        str1.length = temp.length;

        strcpy(str1.data, temp.data);

    }

private:
    char *data;
    int length;

}

然后在主类中:

mystring str1("hi");
mystring str2("matt");

str1 += str2;
cout << str1 << endl;

这个函数正常工作,但是当我运行 valgrind 时出现内存错误。我无法弄清楚为什么会这样。如果有人可以给我任何很棒的提示。

谢谢

【问题讨论】:

  • 你为什么要重新发明轮子?
  • 请将相关错误显示在 valgrind 以及您的构造函数代码中。
  • 请注意,您应该定义一个交换方法。您可能应该有一个特殊的 mystring 构造函数,因此您不必先删除 temp.data 。你应该使用 memcpy,因为你知道长度:strcpy 和 cat 是浪费的。在将 temp 设为新字符串后使用 swap 方法,您只需交换(*this,temp)。 Swap 只会交换指针和长度。
  • 另一条评论,如果你想要更好的附加性能,你可能想要使用旧的 realloc() 而不是 new 和 delete。通常分配器可以在块的末尾找到新的内存,这意味着它不需要将旧数据移动到新位置:它只是扩展分配块。

标签: c++ memory operator-overloading valgrind


【解决方案1】:

首先,你的意思不是:

 strcat(str1.data, str1.data);

但是:

 strcat(str1.data, str2.data);

其次,您希望str2.data 去哪里?这是一个记忆涂鸦,因此是 valgrind 错误。令人惊讶的是,它不只是崩溃。

您需要为组合长度重新分配足够的存储空间,复制原始字符串并释放str1.data,然后再将其重新分配给新存储空间。

根据更新后的帖子:

friend void operator+=(mystring& str1, const mystring& str2)
    {
        // Not using a temp mystring here, as the temp never really maintains its state as a mystring
        // I am assuming length is the length of the string, not the storage. Not the best design if you consider resizing the the string to less than the storage
        int newStringLength = str1.length + str2.length;
        char* newStorage = new char[newStringLength +  1];

        strcpy(newStorage, str1.data);
        // strcat has to scan from the start of the string; we do not need to.
        strcpy(newStorage + str1.length, str2.data);

        delete[] str1.data;

        str1.length = newStringLength ;
        str1.data = newStorage;

         // Haven't though about the case where str2 is an alias for str1.
    }

【讨论】:

  • 感谢您的回复。我已经更改了我的代码以尝试使用您的方法,但它仍然给我内存错误。 OP 已更新。
  • "还没想到 str2 是 str1 的别名。" - 如果你做s += s;,为什么会有什么问题? s 只包含现在重复两次的原始字符串。
  • @visitor。没想到意味着它值得检查。现在快速阅读表明这对我来说是可以的 - 但我可以很容易地想到替代实现,这些实现仅会因别名情况而中断。
【解决方案2】:

你需要在str1中分配额外的内存。

你不能只是盲目地复制到数组的末尾。

【讨论】:

    【解决方案3】:

    你必须分配堆来保存字符并在不再需要时释放堆。

    类似这样的:

    data=new char[length+1];
    

    【讨论】:

      【解决方案4】:
       //it is strange that operator += return void
       // usually we have T& operator += (T const&, T const&) 
        //or T& T::operator +=(T const&)
       friend void operator+=(mystring& str1, const mystring& str2){
          //make sure str1 and str2 are correclty initialzed
          str1.length = str1.length + str2.length;
          //make sure str1.data has enough memory to hold all the data
          //make sure str1.data and str2.data are null terminated strings, not binary data
          strcat(str1.data, str2.data);
      }
      

      【讨论】:

        猜你喜欢
        • 2013-11-09
        • 1970-01-01
        • 1970-01-01
        • 2014-11-18
        • 1970-01-01
        • 2012-11-26
        • 2016-02-19
        • 1970-01-01
        相关资源
        最近更新 更多