You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用malloc/calloc创建含string的结构体动态数组?(禁用new/delete)

问题分析与解决

你的代码存在两个核心问题:

  1. malloc/realloc不调用C++类构造函数:std::string是需要构造的类类型,直接用malloc分配的内存里,person的string成员处于未初始化状态,直接操作会触发未定义行为。
  2. 输入缓冲区残留换行符:cin>>members读取整数后,输入缓冲区里会留下换行符,后续第一个getline会直接读取这个空行,导致输入异常。

另外作业要求使用calloc,你当前用的是malloc,也需要替换。

修正后的代码

#include <iostream>
#include <string>
#include <cstdlib> // 包含calloc、realloc、free的头文件

using namespace std;

struct person{
    string name;
    string post;
    int age;
    char accessLvl;
};

int main(){
    int members = 2;
    // 用calloc分配初始内存,calloc会把内存初始化为0,但依然需要构造string
    person *guard = static_cast<person*>(calloc(members, sizeof(person)));
    if (!guard) {
        cerr << "内存分配失败" << endl;
        return 1;
    }

    // 初始化每个person对象(调用构造函数)
    for (int i = 0; i < members; ++i) {
        new (&guard[i]) person(); // placement new,在已分配内存上构造对象
    }

    cout << "How many guards are active: " << endl;
    cin >> members;
    cin.ignore(); // 跳过输入整数后的换行符

    // 重新分配内存
    person *temp = static_cast<person*>(realloc(guard, sizeof(person)*members));
    if(temp == NULL){
        // 释放前先析构已构造的对象
        for (int i = 0; i < 2; ++i) {
            guard[i].~person();
        }
        free(guard);
        cerr << "内存重分配失败" << endl;
        return 1;
    }

    // 处理realloc后的对象构造/析构
    if (temp != guard) {
        // 对新增的元素调用构造函数
        for (int i = 2; i < members; ++i) {
            new (&temp[i]) person();
        }
    } else {
        if (members > 2) {
            // 内存未扩容时,构造新增元素
            for (int i = 2; i < members; ++i) {
                new (&temp[i]) person();
            }
        } else if (members < 2) {
            // 内存缩容时,析构多余的对象
            for (int i = members; i < 2; ++i) {
                temp[i].~person();
            }
        }
    }

    guard = temp;

    for(int i = 0; i < members; i++){
        cout << "\nname:    ";
        getline(cin, guard[i].name);
        cout << "post:    ";
        getline(cin, guard[i].post);
        cout << "age:    ";
        cin >> guard[i].age;
        cin.ignore(); // 跳过age输入后的换行符
        cout << "Access Level:    ";
        cin >> guard[i].accessLvl;
        cin.ignore(); // 跳过accessLvl输入后的换行符
    }

    for(int i = 0; i < members; i++){
        cout << guard[i].name << endl;
        cout << guard[i].post << endl;
        cout << guard[i].age << endl;
        cout << guard[i].accessLvl << endl;
    }

    // 释放前先析构所有person对象
    for (int i = 0; i < members; ++i) {
        guard[i].~person();
    }
    free(guard);

    return 0;
}

关键修改点说明

  • 替换为calloc:符合作业要求,calloc会将分配的内存初始化为0,但这不足以初始化std::string,仍需用placement new调用构造函数。
  • placement new构造对象:在calloc/realloc分配的内存上,手动调用person的构造函数,确保std::string成员被正确初始化。
  • 手动调用析构函数:在free内存前,必须调用每个person对象的析构函数,否则std::string管理的内存会泄漏。
  • 清理输入缓冲区:每次用cin>>读取数据后,调用cin.ignore()跳过残留的换行符,避免getline读取空行。
  • realloc后的对象管理:如果realloc分配了新内存,需要对新增元素调用构造函数;如果内存缩小,需要析构多余的对象。

内容的提问来源于stack exchange,提问作者user32782935

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 07:17:31