"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 仍然有内存泄漏。尽量避免动态分配(尽管您将需要动态分配每个 String
的 buffer
指针指向的缓冲区)。
简介
我正在定义我自己的 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 仍然有内存泄漏。尽量避免动态分配(尽管您将需要动态分配每个 String
的 buffer
指针指向的缓冲区)。