c ++指向其成员为指针的Structure的指针

时间:2015-07-28 18:43:27

标签: c++

大家好我正在完成一项任务,当给出一个结构及其成员时,我将不得不使用动态内存分配来初始化成员。这是我用过的代码:

# 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 ;
}

任何人都可以告诉我为什么名字不打印。提前谢谢。

2 个答案:

答案 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;
}