为字符串类创建复制构造函数

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 mstringdelete[] mstring @unknownSPY 是的,已修复。您还可以添加检查是否相等,但它是基于意见的。 我推荐if (mstring==str) return; 而不是strcmp()。这里的问题是关于别名的。 @DanAllen 都是 C 风格的字符串,这将如何工作? 这里的危险是delete[] mstring正在删除str,因为它是一个别名。实际上,您需要处理指向“内部”mstring 某处的str。假设str==mstring+1 你的测试是假的,但代码仍然会失败。

以上是关于为字符串类创建复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

如何为派生类创建构造函数? [复制]

c++ 类的复制函数

c++,类的对象作为形参时一定会调用复制构造函数吗?

c++ 复制构造函数和析构函数

为啥子类不能使用基类受保护的构造函数创建新对象?

复制构造函数中的c ++用户定义成员