xCode 类 中的 c++ 析构函数问题
xCode issue with c++ Destructor in classes
我仍在学习 C++,现在正在努力理解构造函数和析构函数。
每当我使用构造函数和析构函数时,我总是收到以下错误。
在我的 class 中。
test(32992,0x100394380) malloc: * error for object 0x100707010:
pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug (lldb)
虽然我可以通过删除析构函数来消除错误,但我知道这不是一个好的编程,因为我必须释放内存。
这是我的代码。
#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;
}
}
问题是您将参数按值 传递给avg()
。您的示例调用了两个不同的东西 s
,因此我将通过调用 s_main
和 s_avg
.
来尝试区分它们
当您按值传递参数时,C++ 会将 s_main
中的数据复制到 s_avg
。这是通过 复制构造函数 完成的。您可以指定自己的复制构造函数,但如果您不这样做,编译器会为您提供一个。默认的复制构造函数只是将数据复制过来;在您的情况下, student
由指针组成,因此默认的复制构造函数复制指针。 它不复制指针指向的数据。
因为s_avg
是avg()
本地的,avg
必须在returns时销毁s_avg
。因此,avg()
在第 37 行末尾的 s_avg
上调用了 student
的析构函数。实际上,这意味着 avg()
删除了 s_main[0]
中的指针,并且s_main[1]
当 returns.
这为 main()
设置了问题。因为 s_main[0]
和 s_main[1]
是 main()
本地的,所以 main
在 returns 时必须销毁 s_main[0]
和 s_main[1]
。因此,main()
在第 47 行末尾调用 s_main[0]
和 s_main[1]
上的 student
的析构函数。和以前一样,析构函数尝试删除 [=29] 中的指针=] 和 s_main[1]
-- 但它们已经被删除了!因此你的问题。
有几种方法可以解决这个问题。一种是遵守 Igor 的建议:您实际上不需要此处的指示。但是,我可以想象,也许您需要针对实际场景而不是这个玩具场景的指示。在这种情况下,另一种处理方法是通过引用 将参数传递给 avg()
。在大多数情况下,这确实是在 C++ 中传递参数的正确方法,无论如何:您不必担心复制构造函数或 C++ 擅长的任何奇怪的事情。准确地说,您应该将第 12 行更改为上面写着
friend float avg(student &);
然后将第 28 行更改为
float avg(student & s){
然后就可以正常工作了。
不过严格来说,您应该使用 constant 引用,除非您打算以某种方式修改数据(这可能会发生)。在这种情况下,将第 12 行更改为
friend float avg(const student &);
第 28 行到
float avg(const student & s){
再说一遍,它会很有魅力。
但实际上,伊戈尔是对的。现代 C++ 旨在帮助您避免使用指针,正是因为跟踪它们非常困难,而且错误的后果非常危险。通过引用传递就是一个很好的例子。所以除非你绝对必须使用它们,否则请避免使用指针。
我仍在学习 C++,现在正在努力理解构造函数和析构函数。
每当我使用构造函数和析构函数时,我总是收到以下错误。 在我的 class 中。
test(32992,0x100394380) malloc: * error for object 0x100707010: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug (lldb)
虽然我可以通过删除析构函数来消除错误,但我知道这不是一个好的编程,因为我必须释放内存。
这是我的代码。
#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;
}
}
问题是您将参数按值 传递给avg()
。您的示例调用了两个不同的东西 s
,因此我将通过调用 s_main
和 s_avg
.
当您按值传递参数时,C++ 会将 s_main
中的数据复制到 s_avg
。这是通过 复制构造函数 完成的。您可以指定自己的复制构造函数,但如果您不这样做,编译器会为您提供一个。默认的复制构造函数只是将数据复制过来;在您的情况下, student
由指针组成,因此默认的复制构造函数复制指针。 它不复制指针指向的数据。
因为s_avg
是avg()
本地的,avg
必须在returns时销毁s_avg
。因此,avg()
在第 37 行末尾的 s_avg
上调用了 student
的析构函数。实际上,这意味着 avg()
删除了 s_main[0]
中的指针,并且s_main[1]
当 returns.
这为 main()
设置了问题。因为 s_main[0]
和 s_main[1]
是 main()
本地的,所以 main
在 returns 时必须销毁 s_main[0]
和 s_main[1]
。因此,main()
在第 47 行末尾调用 s_main[0]
和 s_main[1]
上的 student
的析构函数。和以前一样,析构函数尝试删除 [=29] 中的指针=] 和 s_main[1]
-- 但它们已经被删除了!因此你的问题。
有几种方法可以解决这个问题。一种是遵守 Igor 的建议:您实际上不需要此处的指示。但是,我可以想象,也许您需要针对实际场景而不是这个玩具场景的指示。在这种情况下,另一种处理方法是通过引用 将参数传递给 avg()
。在大多数情况下,这确实是在 C++ 中传递参数的正确方法,无论如何:您不必担心复制构造函数或 C++ 擅长的任何奇怪的事情。准确地说,您应该将第 12 行更改为上面写着
friend float avg(student &);
然后将第 28 行更改为
float avg(student & s){
然后就可以正常工作了。
不过严格来说,您应该使用 constant 引用,除非您打算以某种方式修改数据(这可能会发生)。在这种情况下,将第 12 行更改为
friend float avg(const student &);
第 28 行到
float avg(const student & s){
再说一遍,它会很有魅力。
但实际上,伊戈尔是对的。现代 C++ 旨在帮助您避免使用指针,正是因为跟踪它们非常困难,而且错误的后果非常危险。通过引用传递就是一个很好的例子。所以除非你绝对必须使用它们,否则请避免使用指针。