【问题标题】:definition of "operator +=" behaving unexpectedly“操作员+=”行为异常的定义
【发布时间】:2020-10-02 04:09:09
【问题描述】:

简介

我正在定义我自己的 String 类。除了我打算用来连接Strings+= 的定义之外,一切都很好

//expected behaviour
String c = "foo";
String d = "lala";

c+=d;
cout<<c;

应该输出:

foolala

我遇到了一个问题,因为它似乎确实可以正常工作,除了最后一位似乎没有传递指针。

这是代码(我省略了大部分其他定义,因为我认为它们对此没有用处)


代码

class String{

    private:
        unsigned int SizeS;
        char *Buffer;

    public:
        String():SizeS(0){}

        String(unsigned int i):SizeS(i){Buffer=new char[SizeS];}

        String(const char *string)
        {
            //defines the initialiser
            SizeS = strlen(string);                 //find out the length of the string
            Buffer = new char[SizeS];               //allocate space for the entire string+1 for terminator
            memcpy(Buffer,string,SizeS);            //copy to buffer the whole thing
            Buffer[SizeS]=0;                        //terminate the buffer with an end character
        }

        char * GetBuffer() const { return this->Buffer; }

        String (const String& copied) :SizeS(copied.SizeS)
        {
            // defines how copying  works
            Buffer = new char[SizeS];
            memcpy(Buffer,copied.Buffer,SizeS);
        }


        // this is where the issue is ------------------
        String* operator += (const String& to_concat)
        {
            unsigned int newSize = this->SizeS + to_concat.SizeS;
            String *p = new String(newSize) ;
            memcpy(p->Buffer,this->Buffer,this->SizeS);
            memcpy(p->Buffer+this->SizeS,to_concat.Buffer,to_concat.SizeS);

            std::cout<<p->Buffer<<std::endl;

            return p;
        }
        // this is where the issue ends ------------------
};

std::ostream&  operator<< (std::ostream& stream, const String& other) { stream << other.GetBuffer(); return stream; }


int main()
{
    String c="foo";
    std::cout<<c<<std::endl;
    c += c;
    std::cout<<c<<std::endl;
}

预期输出

foo
foofoo
foofoo

实际输出

foo 
foofoo
foo

问题

我做错了什么?据我了解,我用指针p 覆盖了指针c,但似乎c 没有改变。这是为什么呢?


解决方案

在阅读了 cmets 和建议后,我想出了这个可行的解决方案。

        String& operator += (const String& to_concat)
        {
            unsigned int newSize = this->SizeS + to_concat.SizeS;
            char* p = new char[newSize];

            memcpy(p,this->Buffer,this->SizeS);
            memcpy(p+this->SizeS,to_concat.Buffer,to_concat.SizeS);

            delete[](this->Buffer);

            this->Buffer=p;
            this->SizeS=newSize;

            return *this;
        }

【问题讨论】:

  • 请包含所有相关代码,例如缺少的构造函数。问题应包含minimal reproducible example
  • 你应该将结果连接到 *this->Buffer
  • 您需要检查所有内存分配和零 (nul) 终止符的写入 - 它们无法始终如一地工作。您的构造函数将Buffer 分配为SizeS+1 字符并通过写入Buffer[SizeS+1] 来完成。这会导致未定义的行为。您的 operator+=() 有相反的问题 - 它没有分配足够的字符来存储 nul 字符,但也没有将 nul 字符写入缓冲区。您的operator&lt;&lt;()operator+=() 中的输出语句都假定存在nul 终止符,如果不存在则具有未定义的行为...
  • 不要让我知道operator+=() 返回一个指向动态分配的String 的指针。这是等待发生的内存泄漏。
  • @Peter 它不是在等待;内存泄漏就在程序中。

标签: c++ class pointers operator-overloading


【解决方案1】:

因为你没有写任何代码来改变c

没有“指针c”,即使有,你也不会覆盖它。

您的 += 使用原始两个字符串中的数据创建一个新的、动态分配的字符串,然后返回一个指向它的指针,然后您的程序将其丢弃(顺便说一下,泄漏了该新字符串)。

您应该修改this 中的缓冲区,而不是创建和返回p(然后,按照惯例,将*this 作为String&amp; 返回以允许链接)。

此外,+= 运算符不应产生输出。


+ 操作符的工作方式与您的操作方式类似,因为它们应该生成新对象,但您实际上不应该为此使用 new — 您仍然会有内存泄漏.尽量避免动态分配(尽管您将需要动态分配每个Stringbuffer 指针指向的缓冲区)。

【讨论】:

  • this 中分配更多空间不是不好的做法吗?我不会冒着写在那个寄存器末尾的东西的风险吗?
  • 如果新字符串不适合您的旧对象,那么您必须重新分配缓冲区或拒绝执行该操作。作为类设计者,管理内存是你的职责。
  • @cstml 什么寄存器?
  • @AsteroidsWithWings 对不起,我的评论实际上是完全错误的,误解了你的建议。我现在明白问题出在哪里以及如何解决它。将发布更正来源的更新编辑。
  • @AsteroidsWithWings 和寄存器我的意思是内存块。在我的误解中,我以为您是在说将它们添加到同一个内存块中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
相关资源
最近更新 更多