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

问题描述

我目前正在开发一个项目,该项目是一个门票存储系统,将每个门票持有者存储为一个对象。

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

我面临的主要问题是在初始化每个对象的 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];

在这种情况下,您还需要为类添加一个默认构造函数

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 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,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;
}