C++ 当这些对象中的任何一个没有超出范围时,为什么调用析构函数?
当我从代码中删除析构函数时,输出符合我的要求,但如果我手动释放空间,程序就会变得疯狂:(请有人帮帮我,我正在使用code::Blocks IDE并在Linux mint OS中运行C++ 当这些对象中的任何一个没有超出范围时,为什么调用析构函数?,c++,C++,当我从代码中删除析构函数时,输出符合我的要求,但如果我手动释放空间,程序就会变得疯狂:(请有人帮帮我,我正在使用code::Blocks IDE并在Linux mint OS中运行 #包括 #包括 使用名称空间std; 类str { char*p; 内伦; 公众: str(){ len=0; p=零; } str(const char*s); str(const-str&s); ~str(){ cout您没有重载赋值运算符。因此,同一指针被赋值并被删除两次,导致异常。您没有重载赋值运算符。因
#包括
#包括
使用名称空间std;
类str
{
char*p;
内伦;
公众:
str(){
len=0;
p=零;
}
str(const char*s);
str(const-str&s);
~str(){
cout您没有重载赋值运算符。因此,同一指针被赋值并被删除两次,导致异常。您没有重载赋值运算符。因此,同一指针被赋值并被删除两次,导致异常。您没有跳过r加载了赋值运算符。因此,同一指针被赋值并被删除两次,这导致了异常。您没有重载赋值运算符。因此,同一指针被赋值并被删除两次,这导致了异常。请阅读有关该指针的信息。
如果不声明赋值运算符,编译器将生成一个默认赋值运算符,它执行以下操作:
从赋值运算符参数的相应成员中赋值对象的所有成员,调用对象类类型成员的复制赋值运算符,并对所有非类类型(例如int或指针)数据成员进行简单赋值
首先,上面的粗体文本适用于类中的char*p。
在运算符+函数中,tem是堆栈上的一个对象。当函数结束时,tem超出范围,并调用其析构函数。
因此,根据编译器生成的默认赋值运算符将string1的p赋值给tem的p,这意味着string1的p指向与tem的p相同的内存位置,tem的p在超出作用域后被释放!因此,string1没有预期的值。稍后,当string1超出作用域并调用其析构函数时,在同一内存位置上第二次调用delete,从而导致显示的错误。类似地,对于string2
如果您像这样重载赋值运算符,一切都会好起来:
void str::operator=(const str&s) {
delete[] p;
len=s.len;
p=new char[len+1];
strcpy(p,s.p);
}
在这种情况下,tem的p将在调用其析构函数之前被复制
注意:
当您删除析构函数时,它会工作,因为默认
编译器生成的析构函数不会取消分配
已分配内存,但这将泄漏内存,这是不好的
您的代码中还有另一个主要缺陷。请使用删除[]进行以下操作:
释放数组
阅读关于这个问题的文章。
如果不声明赋值运算符,编译器将生成一个默认赋值运算符,它执行以下操作:
从赋值运算符参数的相应成员中赋值对象的所有成员,调用对象类类型成员的复制赋值运算符,并对所有非类类型(例如int或指针)数据成员进行简单赋值
首先,上面的粗体文本适用于类中的char*p。
在运算符+函数中,tem是堆栈上的一个对象。当函数结束时,tem超出范围,并调用其析构函数。
因此,根据编译器生成的默认赋值运算符将string1的p赋值给tem的p,这意味着string1的p指向与tem的p相同的内存位置,tem的p在超出作用域后被释放!因此,string1没有预期的值。稍后,当string1超出作用域并调用其析构函数时,在同一内存位置上第二次调用delete,从而导致显示的错误。类似地,对于string2
如果您像这样重载赋值运算符,一切都会好起来:
void str::operator=(const str&s) {
delete[] p;
len=s.len;
p=new char[len+1];
strcpy(p,s.p);
}
在这种情况下,tem的p将在调用其析构函数之前被复制
注意:
当您删除析构函数时,它会工作,因为默认
编译器生成的析构函数不会取消分配
已分配内存,但这将泄漏内存,这是不好的
您的代码中还有另一个主要缺陷。请使用删除[]进行以下操作:
释放数组
阅读关于这个问题的文章。
如果不声明赋值运算符,编译器将生成一个默认赋值运算符,它执行以下操作:
从赋值运算符参数的相应成员中赋值对象的所有成员,调用对象类类型成员的复制赋值运算符,并对所有非类类型(例如int或指针)数据成员进行简单赋值
首先,上面的粗体文本适用于类中的char*p。
在运算符+函数中,tem是堆栈上的一个对象。当函数结束时,tem超出范围,并调用其析构函数。
因此,根据编译器生成的默认赋值运算符将string1的p赋值给tem的p,这意味着string1的p指向与tem的p相同的内存位置,tem的p在超出作用域后被释放!因此,string1没有预期的值。稍后,当string1超出作用域并调用其析构函数时,在同一内存位置上第二次调用delete,从而导致显示的错误。类似地,对于string2
如果您像这样重载赋值运算符,一切都会好起来:
void str::operator=(const str&s) {
delete[] p;
len=s.len;
p=new char[len+1];
strcpy(p,s.p);
}
在这种情况下,tem的p将在调用其析构函数之前被复制
注意:
当您删除析构函数时,它会工作,因为默认
编译器生成的析构函数不会取消分配
已分配内存,但这将泄漏内存,这是不好的
您的代码中还有另一个主要缺陷。请使用删除[]进行以下操作:
释放数组
阅读关于这个问题的文章。
当你这样做的时候