大家好我正在完成一项任务,当给出一个结构及其成员时,我将不得不使用动态内存分配来初始化成员。这是我用过的代码:
# include <iostream>
# include <string>
using namespace std;
结构
struct Student
{
char * name;
float gpa;
} ;
PROTOTYPES
Student * createStudent(char name[], float gpa);
int main ()
{
int length ;
float gpa ;
char *p;
Student *myPointer ;
Student myStudent ;
myPointer = &myStudent;
cout << " Please enter number of characters you want to enter " << endl;
cin >> length ;
length = length + 1;
p= new char [length +1];
cout << " Please enter name " << endl;
cin >> p ;
cout << " please enter gpa "<< endl;
cin >> gpa ;
myPointer = createStudent (p,gpa);
cout << myPointer->gpa;
cout << (*myPointer).name << endl;
打印名称时出现错误,但是当我在打印前看到名称的值时,显示与用户输入的名称相同:
delete[]p;
p = 0;
system("pause");
return 0;
}
此函数创建一个学生对象,并指定传递给学生对象的名称和gpa,并返回学生对象的指针:
Student * createStudent( char name[], float gpa )
{
Student *studentPtr ;
Student studentObject;
studentPtr = &studentObject;
studentPtr-> name = name;
studentPtr-> gpa = gpa ;
return studentPtr ;
}
任何人都可以告诉我为什么名字不打印。提前谢谢。
答案 0 :(得分:3)
studentObject
在堆栈上分配,即它具有自动存储持续时间,这意味着它将在函数返回时被销毁。指针不会保持活着状态。
这意味着myPointer
是一个悬垂的指针;解除引用它(myPointer->
)会调用未定义的行为。
要更正它,只需按值返回对象:
Student createStudent(char name[], float gpa)
{
Student studentObject;
studentPtr.name = name;
studentPtr.gpa = gpa;
return studentObject;
}
和
Student myStudent = createStudent(p, gpa);
编辑:我刚刚读到您需要使用动态内存分配初始化成员。上述解决方案不会这样做。对于动态内存分配,您必须使用new
:
Student* createStudent(char name[], float gpa)
{
Student* studentPtr = new Student;
studentPtr->name = name;
studentPtr->gpa = gpa;
return studentPtr;
}
和
myPointer = createStudent(p, gpa);
// use
delete myPointer;
为studentPtr->name
分配new
的新缓冲区可能不是一个好主意,而不仅仅是指定指针;你可以看到 Mateusz 的答案。
但当然这只是你教授的一个不好的例子。正如 gd1 所提到的,这种代码不是很好的现代C ++,不应该以真正的生产代码结束。
答案 1 :(得分:1)
这是完全错误的:
Student* createStudent( char name[], float gpa )
{
Student *studentPtr ;
Student studentObject;
studentPtr = &studentObject;
studentPtr-> name = name;
studentPtr-> gpa = gpa ;
return studentPtr ;
}
studentObject
是一个本地对象,在函数结束后被销毁。返回指针和/或对局部变量的引用是一个错误 - 您应该从编译器收到警告。
另一个问题是这一行:
studentPtr->name = name;
你现在做什么:在main()
中分配一块内存,将其传递给一个对象,该对象可以使用这个内存,然后在main()
中释放它。你不应该这样做 - 对象应该对其内容负责。你确定,这个责任应该是你的吗?我建议你:
Student* createStudent( char name[], float gpa )
{
size_t name_len = strlen(name);
Student studentObject;
studentObject.name = new char[name_len+1];
strncpy(studentObject.name, name, name_len + 1);
studentObject.gpa = gpa ;
return studentObject;
}
用于销毁Student
的类比功能:
void destroyStudent(Student* student)
{
delete[] student->name;
student->name = nullptr;
}
明显的解决方案是使用std::string
,但我认为,你有充分的理由手动完成所有这些......不是吗?
哦,如果你真的需要返回Student
作为指针:
Student* createStudent( char name[], float gpa )
{
size_t name_len = strlen(name);
Student* studentPtr = new Student;
studentPtr->name = new char[name_len+1];
strncpy(studentPtr->name, name, name_len + 1);
studentPtr-> gpa = gpa ;
return studentPtr;
}
void destroyStudent(Student* student)
{
delete[] student->name;
student->name = nullptr;
delete[] student;
}