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

循环读取字符串入队数据重复:char*地址始终相同的问题及修复

解决队列节点data指向相同地址的问题

问题原因分析

你遇到的问题本质是局部变量的内存复用和**std::string::c_str()返回值的生命周期限制**:

  • 每次调用read_input()时,局部变量string s是在栈上创建的。当函数执行完毕返回后,s会被销毁,其底层存储字符串的字符数组内存也会被栈回收。
  • 由于循环调用read_input(),编译器会优化栈空间的使用,每次创建的s都会复用同一个栈地址。这就导致每次调用s.c_str()返回的都是同一个内存地址。
  • 更严重的是,当read_input()返回后,这个地址的内容是未定义的(栈内存已经被释放),后续访问队列节点的data会导致未定义行为,而你看到的“所有节点data值相同”只是因为每次循环都覆盖了同一个地址的内容。

修复方案

这里提供几种不同的修复思路,你可以根据自己的需求选择:

方案1:为每个字符串分配独立的堆内存

手动拷贝字符串到堆内存中,让每个节点的data指向独立的内存空间:

void read_input(Queue *q) {
    string s;
    int p;
    cin >> s >> p;
    // 分配足够的内存存储字符串(+1是为了末尾的'\0')
    char* str_buffer = new char[s.size() + 1];
    // 拷贝字符串内容到堆内存
    strcpy(str_buffer, s.c_str());
    // 将堆内存的指针传入队列
    push(q, str_buffer, p);
}

⚠️ 注意:这种方式需要你在后续销毁队列节点时,手动调用delete[]释放data指向的内存,避免内存泄漏。

方案2:存储std::string的指针而非const char*

修改Node结构体的data类型为std::string*,直接存储动态创建的string对象指针:

// 修改结构体定义
struct Node {
    std::string* data;
    Node *l, *r;
};

// 修改read_input函数
void read_input(Queue *q) {
    string s;
    int p;
    cin >> s >> p;
    // 新建一个string对象,拷贝输入的字符串
    push(q, new std::string(s), p);
}

这种方式比方案1更安全,因为std::string会自动管理底层字符数组的内存。同样,销毁节点时需要调用delete释放data指向的string对象。

方案3:直接在Node中存储std::string(最推荐)

如果可以修改Node结构体的定义,直接存储std::string而非指针是最安全、最省心的方式:

// 修改结构体定义
struct Node {
    std::string data;
    Node *l, *r;
};

// 调整push函数的参数(假设可以修改)
void push(Queue *q, const std::string& data, int priority) {
    Node *n = new Node;
    n->data = data; // 直接拷贝字符串
    // 后续入队逻辑...
}

// 修改read_input函数
void read_input(Queue *q) {
    string s;
    int p;
    cin >> s >> p;
    push(q, s, p);
}

这种方式完全避免了指针和内存管理的问题,std::string的拷贝构造函数会自动为每个节点创建独立的字符串副本,从根源上解决地址重复的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:33:48