如何正确地将输入读入动态分配的对象数组

How to correctly read inputs into a dynamically allocated array of objects

我目前正在做一个项目,它是一个票存储系统,将每个持票人存储为一个对象。

为了输入值,我使用了参数化构造函数。在主函数中,我为这些对象的数组声明了一个动态内存块。

我面临的主要问题是在初始化每个对象的for循环中,循环只运行一次,然后终止。这是代码:

#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;
class node
{
    string holder_name;
    int age;

public:
    node(string a, int b)
    {
        holder_name = a;
        age = b;
    }

    void view()
    {
        cout << "Name: " << holder_name << endl;
        cout << "Age: " << age << endl;
    }
};
int main()
{
    int count, i;
    cout << "Enter no of nodes" << endl;
    cin >> count;
    node *arr = (node *)malloc(sizeof(node) * count);

    for (i = 0; i < count; i++)
    {
        int b;
        string str;
        cout << "Enter name" << endl;
        cin >> str;
        cout << "Enter age" << endl;
        cin >> b;
        arr[i] = node(str, b);
        arr[i].view();
    }
    return 0;
}

赋值 arr[i]=node(str,b) 需要左侧的有效(构造)值。 malloc 分配数组内存但不初始化数组元素。 C++ new 运算符就是为了这样的目的。

node *arr= new node[count];

只是为了比较表达式

node *arr= (node*)malloc(sizeof(node)*count);
node *arr= new node[count];

第二个表达式比使用的 C malloc 更短,更安全并且可以自动执行大量工作。但如果您不处理手动内存管理,那就更好了。

auto arr= std::vector<node>(count);

这是一个很好的例子,为什么在 C++ 中不使用 malloc,当你为你的 node 分配内存时,元素没有被初始化。

C++ 中的分配是通过 new 完成的,以防止上述问题:

node *arr= new node[count];

在这种情况下,您还需要向 class

添加默认构造函数

node() = default;node(){};

但是,更好的解决方案是使用可调整大小的 containers provided by C++ 容器库之一,例如 std::vector:

#include <vector>
int main()
{
    int count, i;
    cout << "Enter no of nodes" << endl;
    cin >> count;
    std::vector<node> arr; // now you have a resizable container
    for (i = 0; i < count; i++)
    {
        int b;
        string str;
        cout << "Enter name" << endl;
        cin >> str;
        cout << "Enter age" << endl;
        cin >> b;
        arr.push_back(node(str, b)); // keep adding elements
        arr[i].view();
    }
}

在这里您还可以创建具有 S.M 中建议的初始大小的向量。答案,它确实取决于您对容器的期望大小,如果它在较大的一侧更好,因为它避免了内存重新分配,在这种情况下,插入将与您在原始代码中的完全相同。

脚注

我要补充一点,using namespace std;不是最推荐的技术,你可以在这里找到推理和替代方法:

Why is "using namespace std;" considered bad practice?

在你的 class 中使用构造函数和析构函数。

    class node{
string holder_name;
int age;
public:
node(){
    
}
node(string a, int b)
{
    holder_name=a;
    age=b;
}

void view()
{
    cout<<"Name: "<<holder_name<<endl;
    cout<<"Age: "<<age<<endl;
}
~node()
{
    
}

也不要在 C++ 中使用 malloc 进行分配 而是使用

    node*  arr= new node[count];

编辑如下(对您的代码进行最少的更改)。

#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;
class node
{
    string* holder_name;
    int age;
public:
    node(string a, int b)
    {
        holder_name = new string(a);
        age = b;
    }
    ~node()
    {
        Dispose();
    }

    void Dispose()
    {
        if (holder_name)
        {
            delete holder_name;
            holder_name = NULL;
        }
    }

    void view()
    {
        cout << "Name: " << *holder_name << endl;
        cout << "Age: " << age << endl;
    }

    // copy assignment
    void operator = (const node& D) {
        if (holder_name)
            delete holder_name;
        holder_name = new string( *D.holder_name );
        age = D.age;
    }
};

int main()
{
    int count, i;
    cout << "Enter no of nodes" << endl;
    cin >> count;
    node* arr = (node*)malloc(sizeof(node) * count);
    memset(arr, 0, sizeof(node) * count);
    

    for (i = 0; i < count; i++)
    {
        int b;
        string str;
        cout << "Enter name" << endl;
        cin >> str;
        cout << "Enter age" << endl;
        cin >> b;
        arr[i] = node(str, b);
        arr[i].view();
    }

    
    // avoid memory leak
    for (i = 0; i < count; i++)
        arr[i].Dispose();
    free(arr);

    return 0;
}