为字符串类创建复制构造函数
Posted
技术标签:
【中文标题】为字符串类创建复制构造函数【英文标题】:Creating a copy constructor for a string class 【发布时间】:2015-07-15 14:13:11 【问题描述】:我正在创建自己的字符串类(作为练习),我知道我需要一个复制构造函数和一个重载的 = 赋值运算符,但不知道从哪里开始。
这个类很简单,只存储字符串,例如
char* m_string;
我目前有一个标准构造函数 (MyString(const char* str)
),它接受 const char* string
,然后通过 m_string = new char[numChars + 1]
分配必要的内存(在计算参数中的字符数之后)
显然,我需要能够使用赋值运算符将一个字符串分配给另一个字符串,但也希望能够从另一个字符串对象构造一个字符串对象。即
MyString(const MyString& str)
关于重载=赋值运算符
然后我是否可以根据字符数获取 rhs 和 lhs 的长度,然后根据 rhs 比 lhs 长还是短来调整内存量?
我不一定想要完整的答案,因为我认为您不会从被告知答案中学到任何东西,但我们将不胜感激提供一些正确方向的建议和指导。
谢谢
【问题讨论】:
【参考方案1】:复制构造函数必须为str
的有效载荷分配内存,然后复制内容。这与您已有的构造函数非常相似,只是 char *
不是直接作为参数给出,而是在 str
中“隐藏”。
赋值运算符必须考虑已经分配的内存。
它可以重用现有分配的内存。如果新内容的长度相同或更短,则此方法有效。终止 \0
将使最后的额外内存对常规字符串处理函数不可见。
如果新字符串较大,则必须释放旧内存并分配足够大小的新块。
为了安全起见,建议检查自分配,即this == &rhs
。如果您删除内存然后尝试从中读取,您会遇到问题。这允许a = a
工作。
返回对修改后对象的引用也是常见的做法。
这允许a = b = c
工作。
【讨论】:
我是这么想的,我是不是先把Lhs的内存删掉,然后再用另一个new
完全重新分配?
@unknownSPY 是一个构造函数。没有分配的内存要删除。
@unknownSPY 不,因为它是一个构造函数,所以没有什么可删除的。
啊好的-谢谢,这是有道理的。在重载 = 赋值运算符的情况下呢?
@unknownSPY 对于operator=()
,你是对的,你有一个现有的对象,它的内存必须被释放(或重用,如果现有的缓冲区足够大并且你想减少内存分配)到避免内存泄漏。【参考方案2】:
这可能会起作用
MyString(const MyString & str)
m_string = new char[str.length() + 1];
. . . /// same as MyString(const char * str)'s definition
对于operator =
operator =(const char * str)
if (strcmp(mstring, str) == 0) return; /// Optional
delete[] mstring;
mstring = new char[strlen(str) + 1];
. . . /// Same as the constructor
【讨论】:
应该delete mstring
是delete[] mstring
?
@unknownSPY 是的,已修复。您还可以添加检查是否相等,但它是基于意见的。
我推荐if (mstring==str) return;
而不是strcmp()
。这里的问题是关于别名的。
@DanAllen 都是 C 风格的字符串,这将如何工作?
这里的危险是delete[] mstring
正在删除str
,因为它是一个别名。实际上,您需要处理指向“内部”mstring 某处的str
。假设str==mstring+1
你的测试是假的,但代码仍然会失败。以上是关于为字符串类创建复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章