【问题标题】:Scope of struct object in c++ created without new keyword在没有 new 关键字的情况下创建的 c++ 中结构对象的范围
【发布时间】:2016-07-09 06:53:32
【问题描述】:

来自 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;
}

【问题讨论】:

  • 由于您来自Java背景,我真的建议您了解变量和指针之间的区别!还要记住,每当您将某些内容作为参数传递时,它都会被复制。当您改用指针时,您会得到 Java 行为。然后你还必须使用new 关键字。

标签: c++ scope declaration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    变量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;
    }
    

    【讨论】:

      【解决方案3】:

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

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

      复制是使用对象的复制构造函数完成的,在这种情况下是编译器提供的。它将依次调用结构的字符串和向量成员上的复制构造函数。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2011-07-07
          • 1970-01-01
          • 2011-12-07
          • 2011-11-08
          • 2022-06-13
          • 2016-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多