如何在C++中从函数返回一个结构体?

43

我在几个不同的论坛上尝试过,但似乎无法得到直接的答案,如何使此函数返回结构体?如果我尝试“return newStudent;”,我会收到错误提示:“不存在从studentType到studentType的合适用户定义转换。”

// Input function
studentType newStudent()
{   
    struct studentType
    {
        string studentID;
        string firstName;
        string lastName;
        string subjectName;
        string courseGrade;

        int arrayMarks[4];

        double avgMarks;

    } newStudent;

    cout << "\nPlease enter student information:\n";

    cout << "\nFirst Name: ";
    cin >> newStudent.firstName;

    cout << "\nLast Name: ";
    cin >> newStudent.lastName;

    cout << "\nStudent ID: ";
    cin >> newStudent.studentID;

    cout << "\nSubject Name: ";
    cin >> newStudent.subjectName;

    for (int i = 0; i < NO_OF_TEST; i++)
    {   cout << "\nTest " << i+1 << " mark: ";
        cin >> newStudent.arrayMarks[i];
    }

    newStudent.avgMarks = calculate_avg(newStudent.arrayMarks,NO_OF_TEST );
    newStudent.courseGrade = calculate_grade (newStudent.avgMarks);

}

2
你似乎声明了两个版本的 studentType 定义:一个在函数外部,另一个在函数内部。你应该只有一个定义,就是在函数外部的那个。 - Dietmar Kühl
或者,您可以在堆上分配它,并返回studentType类型的指针。 - Mike G
5个回答

45

这是您的代码的编辑版本,它基于ISO C++,并与G++兼容:

#include <string.h>
#include <iostream>
using namespace std;

#define NO_OF_TEST 1

struct studentType {
    string studentID;
    string firstName;
    string lastName;
    string subjectName;
    string courseGrade;
    int arrayMarks[4];
    double avgMarks;
};

studentType input() {
    studentType newStudent;
    cout << "\nPlease enter student information:\n";

    cout << "\nFirst Name: ";
    cin >> newStudent.firstName;

    cout << "\nLast Name: ";
    cin >> newStudent.lastName;

    cout << "\nStudent ID: ";
    cin >> newStudent.studentID;

    cout << "\nSubject Name: ";
    cin >> newStudent.subjectName;

    for (int i = 0; i < NO_OF_TEST; i++) {
        cout << "\nTest " << i+1 << " mark: ";
        cin >> newStudent.arrayMarks[i];
    }

    return newStudent;
}

int main() {
    studentType s;
    s = input();

    cout <<"\n========"<< endl << "Collected the details of "
        << s.firstName << endl;

    return 0;
}

2
使用指针来防止复制构造函数不是更有效吗? - Javier Cabero
@JavierCabero 我认为会自动进行复制省略...因此根本没有复制!但如果你真的想要管理它,你可以在结构体对象上实现一些左值移动。 - Sandburg
2
在程序中,返回一个已分配在栈上的变量不好吗? - Little Helper
1
@LittleHelper:只有在返回引用时才会出现问题。 - rkgghz

24
你有一个作用域问题。在函数内部定义结构体,而不是在其内部定义。

16

现在(C++14),您可以按如下方式返回在函数内部定义的本地结构体:

auto f()
{
    struct S
    {
      int a;
      double b;
    } s;
    s.a = 42;
    s.b = 42.0;
    return s;
}

auto x = f();
a = x.a;
b = x.b;

8
studentType newStudent() // studentType doesn't exist here
{   
    struct studentType // it only exists within the function
    {
        string studentID;
        string firstName;
        string lastName;
        string subjectName;
        string courseGrade;

        int arrayMarks[4];

        double avgMarks;

    } newStudent;
...

将其移至函数外部:
struct studentType
{
    string studentID;
    string firstName;
    string lastName;
    string subjectName;
    string courseGrade;

    int arrayMarks[4];

    double avgMarks;

};

studentType newStudent()
{
    studentType newStudent
    ...
    return newStudent;
}

由于您没有使用new运算符来创建结构实例,所以在调用newStudent()后它会自动删除吗? - Ramesh-X
2
@Ramesh-X 不可以,因为new创建的是指向堆上创建实例的指针。如果直接返回结构体,则只是将结构体的位数“复制”到调用方分配给函数调用结果的左值中(一个足够聪明的编译器可能只使用调用者提供的位置)。当你返回本地结构时出现问题,这是因为返回一个“指针”(该指针可能是引用,实际上并不需要使用指针来实现)。 - cuddlebugCuller

-1
正如其他人指出的那样,将studentType定义在函数外部。还有一件事,即使你这样做了,也不要在函数内部创建一个局部的studentType实例。该实例位于函数堆栈上,在尝试返回它时将无法使用。但是你可以动态地创建studentType并在函数外部返回指针。

7
如果他创建了一个自动的studentType并通过复制方式返回它,那么复制构造函数将会被调用(如果你没有创建,则会创建一个默认的),因此他不会遇到任何问题。在函数内部声明结构体是他的主要问题 - 目前没有必要动态声明它。 - Zac Howland
据我所知,从函数返回值的默认方法是通过移动而不是复制。毕竟,被调用者不再需要它。 - cuddlebugCuller
2
@cuddlebugCuller 在那个评论发表时,情况并非如此 :) 自2013年以来,移动语义已经被添加和更新了几次。 - Zac Howland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接