我还在学习c++,我现在正在尝试理解构造函数和析构函数。
每当我使用构造函数和析构函数时,我总是得到下面的错误。在我的班上。
test(32992,0x100394380)malloc:***对象0x100707010的错误:未分配释放的指针***在malloc_error_break中设置断点为debug(lldb)
虽然我可以通过删除析构函数来消 debugging 误,但我知道这不是一个好的编程,因为我必须释放内存。
这是我的代码。
#include <iostream>
using namespace std;
class student{
private:
int *age, *mark1,*mark2,*mark3;
string *name;
public:
friend float avg(student);
student(){
age = new int;
mark1 = new int;
mark2 = new int;
mark3 = new int;
name = new string;
cout << "Enter student name: "; cin >> *name;
cout << "Enter student age: "; cin >> *age;
cout << "Enter student 3 marks: "; cin >> *mark1 >> *mark2 >> *mark3;
cout << endl; }
~student(){
delete age;
delete mark1;
delete mark2;
delete mark3;
delete name; }
string returnName(){
return *name; }
};
float avg(student s){
return (double)(*s.mark1+*s.mark2+*s.mark3)/3;}
int main() {
student s[2];
for (int i = 0; i < 2; i++) {
s[i];
cout << "Avg of student " << s[i].returnName() << " is " << avg(s[i]) << endl;
}
}
1条答案
按热度按时间puruo6ea1#
问题是您正在向
avg()
传递参数by value。您的示例调用了两个不同的东西s
,因此我将尝试通过调用它们s_main
和s_avg
来区分它们。当通过值传递参数时,C将
s_main
中的数据复制到s_avg
。这是通过copy constructor完成的。您可以指定自己的复制构造函数,但如果您不指定,编译器会为您提供一个复制构造函数。默认的复制构造函数只复制数据;在本例中,student
由指针组成,因此默认的复制构造函数复制指针。不复制指针指向的数据。因为
s_avg
是avg()
的本地,所以avg
在返回时必须销毁s_avg
。因此,avg()
在第37行末尾的s_avg
上调用student
的析构函数。实际上,这意味着avg()
在返回时会删除s_main[0]
和s_main[1]
中的指针。这就产生了
main()
的问题。因为s_main[0]
和s_main[1]
是main()
的本地,所以main
在返回时必须销毁s_main[0]
和s_main[1]
。因此,main()
在第47行末尾调用s_main[0]
和s_main[1]
上的析构函数。和前面一样,析构函数试图删除s_main[0]
和s_main[1]
中的指针--但是它们已经被删除了!这就是你的问题。有几种方法可以解决这个问题。一是遵守伊戈尔的建议:你不需要指点。然而,我可以想象,也许你需要一个实际场景的指针,而不是这个玩具场景。在这种情况下,另一种处理此问题的方法是通过引用将参数传递给
avg()
。无论如何,这是C中大多数时候传递参数的正确方法:你不必担心复制构造函数或者C++专门研究的那些奇怪的东西。准确地说,您应该更改第12行,使其变为然后把第28行改成
然后它就能正常工作了
严格地说,你应该使用一个常量引用,除非你计划以某种方式修改数据(这可能发生)。在这种情况下,将第12行更改为
第28话
而且,它会像一种魔力一样起作用
但真的伊戈尔说得对。现代C++的设计是为了帮助你避免指针,正是因为跟踪它们是如此困难,错误的后果是如此危险。引用传递就是一个很好的例子。所以避免使用指针,除非你绝对需要使用它们。