"operator +=" 行为异常的定义

definition of "operator +=" behaving unexpectedly

简介

我正在定义我自己的 String class。一切正常,除了我打算用来连接 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 没有改变。这是为什么?


解决方案

阅读评论和建议后,我想到了这个有效的解决方案。

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

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

没有 "pointer c",即使有,您也不会覆盖它。

您的 += 创建一个新的动态分配的字符串,使用来自原始两个字符串的数据,然后 returns 一个指向它的指针,然后您的程序将其丢弃(顺便说一句,泄漏了新的字符串).

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

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


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