类中C++析构函数的 Xcode 问题

Xcode issue with C++ Destructor in classes

本文关键字:Xcode 问题 析构函数 C++ 类中      更新时间:2023-10-16

我仍在学习 c++,我现在试图理解构造函数和析构函数。

每当我使用构造函数和析构函数时,我都会不断收到以下错误。 在我的课堂上。

测试(32992,0x100394380( malloc:* 对象0x100707010错误: 未分配正在释放的指针 *在要调试的malloc_error_break中设置断点 (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_mains_avg来区分它们。

按值传递参数时,C++ 会将s_main中的数据复制到s_avg。这是通过复制构造函数完成的。您可以指定自己的复制构造函数,但当您不指定时,编译器会为您提供一个。默认复制构造函数只是复制数据;在您的情况下,student由指针组成,因此默认的复制构造函数复制指针。它不会复制指针指向的数据。

因为s_avgavg()的本地,avg在返回时必须摧毁s_avg。因此,avg()在第 37 行末尾调用student的析构函数s_avg。实际上,这意味着avg()会删除s_main[0]中的指针,并在返回时s_main[1]

这就给main()设置了问题。因为s_main[0]s_main[1]main()的本地,main必须摧毁s_main[0],并在返回时s_main[1]。因此,main()调用student的析构函数,s_main[0]s_main[1]在第 47 行的末尾。和以前一样,析构函数尝试删除s_main[0]s_main[1]中的指针 - 但它们已被删除!因此你的问题。

有几种方法可以解决此问题。一个是遵守伊戈尔的建议:你在这里真的不需要指针。但是,我可以想象,也许您需要实际场景的指针,而不是这个玩具场景。在这种情况下,解决此问题的另一种方法是通过引用将参数传递给avg()。无论如何,这确实是大多数时候传递参数的正确方法C++:您不必担心复制构造函数或任何C++擅长的奇怪事情。准确地说,您应该更改第 12 行,使其显示为

friend float avg(student &);

然后更改第 28 行,使其显示为

float avg(student & s){

然后它会正常工作。

但严格来说,您应该使用常量引用,除非您计划以某种方式修改数据(这可能会发生(。在这种情况下,将第 12 行更改为

friend float avg(const student &);

和行 28 到

float avg(const student & s){

而且,再一次,它会像一个魅力一样工作。

但实际上,伊戈尔是对的。现代C++旨在帮助您避免指针,正是因为跟踪它们非常困难,错误的后果非常危险。通过引用传递就是一个很好的例子。因此,除非绝对必须使用指针,否则请避免使用指针。