在没有new关键字的情况下创建的c ++中结构对象的范围

Scope of struct object in c++ created without new keyword

来自 Java 背景,以下代码让我感到困惑。这里的混淆是没有 new 关键字的 C++ 对象创建。我正在创建此对象 Student_info info;,然后将其添加到向量中。由于我没有使用 new 关键字创建它,它会在堆栈上分配并在循环退出后被销毁吗?如果是这样,最后一个循环如何能够正确地从向量中提取信息?它不应该抛出异常,因为添加到向量的所有对象都已被销毁吗?

struct Student_info {
    string name;
    vector<double> marks;
};

int main()
{
    int num = 2;

    vector<Student_info> student_infos;
    for (int i = 0; i < 3; i++) {
        Student_info info; //will this object be destroyed once this loop exits?
        cout << "Enter name:";
        cin >> info.name;

        double x;
        cout << "Enter 2 marks";
        for (int j = 0; j < num; j++) {
            cin >> x;
            info.marks.push_back(x);
        }
        student_infos.push_back(info);
    }

    for (int i = 0; i < 3; i++) {
        cout << student_infos[i].name;
        for (int j = 0; j < num; j++) {
            cout << student_infos[i].marks[j];
        }
        cout << endl;
    }
    return 0;
}

是的,info会在循环结束时销毁。 push_backinfo 创建一个新的副本,所以即使 info 被破坏,它的副本仍然存在于向量中。

你是正确的,info 对象将被销毁,但在使用 push_back 时它被 复制 到向量中。其余代码从向量中读取副本而不是原始对象。

http://www.cplusplus.com/reference/vector/vector/push_back/

复制是使用对象的复制构造函数完成的,在本例中,它是由编译器提供的。它将依次调用结构的字符串和向量成员的复制构造函数。

变量的范围info是从变量声明点开始的for语句的块范围。

for (int i = 0; i < 3; i++) {
    Student_info info; //will this object be destroyed once this loop exits?
    //...
}

每次执行循环的新迭代时,都会创建一个名为 info 的新对象。

变量的范围student_infos是声明变量的函数main的最外层块范围。

int main()
{
    vector<Student_info> student_infos;
    //...
}

执行循环时,一个新对象被添加到作为变量info 副本的向量中。该向量不包含对名称为 info 的原始对象的引用。它创建对象的副本并将其存储在内部。

考虑到通常这些循环

for (int i = 0; i < 3; i++) {
    cout << student_infos[i].name;
    for (int j = 0; j < num; j++) {
        cout << student_infos[i].marks[j];
    }
    cout << endl;
}

不安全。最好依赖向量中元素的实际数量。你可以改写

for ( vector<Student_info>::size_type i = 0; i < student_infos.size(); i++)
{
    cout << student_infos[i].name;
    for ( vector<double>::size_type j = 0; j < student_infos[i].marks.size(); j++) 
    {
        cout << student_infos[i].marks[j];
    }
    cout << endl;
}

当push_back是完毕。如果您可以为 Student_info 编写自定义复制构造函数并在那里打印一些内容,您将看到复制构造将被调用。 考虑使用, http://en.cppreference.com/w/cpp/container/vector/emplace_back