【问题标题】:Concatenate two customized string objects in C++?在 C++ 中连接两个自定义字符串对象?
【发布时间】:2015-10-29 14:28:11
【问题描述】:

我正在为家庭作业定义自己的字符串类。我注意到以下代码

class MyString {
public:
    MyString(const char* s = NULL) {len = strlen(s); str = new char[len + 1]; strcpy(str, s);}
    ~MyString() {delete [] str;}
    friend ostream& operator << (ostream& ost, const MyString& s) { ost << s.str; return ost;}
    friend MyString operator + (const MyString &s1, const MyString &s2) { 
        int length = strlen(s1.str) + strlen(s2.str); 

        char *str = new char[length + 1];
        strcpy(str, s1.str);
        strcat(str, s2.str);
        return MyString(str);
    }
private:
    char * str;
    int len;
};

int main () {
    MyString s1 = MyString("hello");
    MyString s2 = MyString("world");
    cout << s1 + s2 << endl;
    return 0;
}

有效,因为返回对象是在最后一刻创建的。但是下面的代码

class MyString {
public:
    MyString(const char* s = NULL) {len = strlen(s); str = new char[len + 1]; strcpy(str, s);}
    ~MyString() {delete [] str;}
    friend ostream& operator << (ostream& ost, const MyString& s) { ost << s.str; return ost;}
    friend MyString operator + (const MyString &s1, const MyString &s2) { 
        int length = strlen(s1.str) + strlen(s2.str); 
        MyString temp;
        temp.str = new char[length + 1];
        strcpy(temp.str, s1.str);
        strcat(temp.str, s2.str);
        return temp;
    }
private:
    char * str;
    int len;
};

int main () {
    MyString s1 = MyString("hello");
    MyString s2 = MyString("world");
    cout << s1 + s2 << endl;
    return 0;
}

没有,给我一个运行时错误。所以我很困惑为什么第二种方法会失败,如果在重载的运算符中定义、修改和返回临时对象。

【问题讨论】:

  • 我强烈推荐两件事:(1)不要使用手动内存管理;相反,环绕std::unique_ptr&lt;char[]&gt;。 (2) 不要使用 C 字符串函数。改用 C++ 标准库算法(特别是,这里应该是 std::copy
  • MyString temp; 使用带有s == nullptr 的构造函数,那么strlen(s) 是UB。
  • 当心:你目前违反了三法则。

标签: c++ string memory dynamic


【解决方案1】:

问题在于,当您在此处默认构造 temp 时:

MyString temp;

你必须执行:

MyString(const char* s = NULL) {len = strlen(s); ... }

空指针上的strlen 未定义。如果您改为将默认参数更改为:

MyString(const char* s = "")

但是,这两种解决方案仍然很差,因为它们都泄漏内存。在前者中,您永远不会 delete[] 临时 str。在后者中,您的默认构造函数分配了一个新的str 成员,然后您立即用新分配的str 成员覆盖它。原件泄露了。

【讨论】:

    【解决方案2】:

    在您的构造函数中,您为字符串分配内存:

    len = strlen(s); str = new char[len + 1]; strcpy(str, s);
    

    所以如果你稍后附加一个字符串;因此没有分配内存。

    创建两个字符串的总和时;你像这样创建你的“总和字符串”:

    MyString temp;
    

    那么分配给str的内存是未知的;因为

    len = strlen(NULL);
    

    如果你想继续;您可以考虑添加两件事:

    • 检查s是否=NULL;然后不分配内存,但这会在以后造成麻烦...
    • 一种分配更多内存的方法;类似 temp.allocate(strlen(s1) + strlen(s2))

    【讨论】:

      【解决方案3】:

      返回是创建一个对象并复制指针。然后在同一地址发生 2 次删除

      【讨论】:

        猜你喜欢
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2012-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-30
        相关资源
        最近更新 更多