我正在为家庭作业定义自己的字符串类。我注意到以下代码
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;
}
不,给我一个运行时错误。所以我很困惑为什么第二种方法失败,如果在重载运算符中定义,修改和返回临时对象。
答案 0 :(得分:2)
问题在于,当您在此处默认构建temp
时:
MyString temp;
你必须执行:
MyString(const char* s = NULL) {len = strlen(s); ... }
空指针上的 strlen
未定义。如果您将默认参数更改为:
MyString(const char* s = "")
然而,两种解决方案仍然很差,因为它们都会泄漏内存。在前者中,您永远不会delete[]
临时str
。在后者中,您的默认构造函数分配了一个新的str
成员,然后您立即使用新分配的str
成员覆盖它。原件被泄露了。
答案 1 :(得分:0)
在构造函数中为字符串分配内存:
len = strlen(s); str = new char[len + 1]; strcpy(str, s);
所以如果你稍后追加一个字符串;因此没有分配内存。
创建两个字符串的总和时;你创建了&#34; sum-string&#34;像这样:
MyString temp;
那么为str分配的内存是未知的;因为
len = strlen(NULL);
如果你想继续;你可以考虑添加两件事:
答案 2 :(得分:0)
返回创建一个对象并复制指针。然后在同一地址上发生2次删除