首页 文章

c指向其成员为指针的结构的指针

提问于
浏览
1

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

# 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 回答

  • 1

    studentObject 在堆栈上分配,即它具有自动存储持续时间,这意味着它将在函数返回时被销毁 . 指针不会保持活着状态 .

    这意味着 myPointer 是一个悬垂的指针;解除引用它( myPointer-> )会调用未定义的行为 .


    要更正它,只需按值返回对象:

    Student createStudent(char name[], float gpa)
    {
        Student studentObject;
        studentPtr.name = name;
        studentPtr.gpa = gpa;
        return studentObject;
    }
    

    Student myStudent = createStudent(p, gpa);
    

    Edit: 我刚刚读到你需要使用动态内存分配初始化成员 . 上述解决方案不会这样做 . 对于动态内存分配,您必须使用 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,不应该以实际的 生产环境 代码结束 .

  • 3

    这是完全错误的:

    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 ,但我认为,你有充分的理由手动完成所有这些......不是吗?

    哦,如果你 really 需要返回 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;
    }
    

相关问题