【问题标题】:Memory allocation with looping in C++在 C++ 中使用循环进行内存分配
【发布时间】:2021-05-18 08:01:52
【问题描述】:

我有一个用于 char 数组的 List 类。我想将 N 个数组从 'a' 推回 'a..a'。

char* x;
SList list;
for (unsigned int i = 1; i < n+1; i++) {
    x = new char[i+1];
    for (unsigned int j = 0; j < i; j++) {
        x[j] = 'a';
    }
    x[i] = '\0';
    list.push_back(&x);
}

但每次,x 都有相同的地址。结果,我的 List 对象包含 N 个指向同一地址的指针。 有没有办法通过正确的内存分配循环推回这些数组?

在询问之前发现了这个question,但它并没有为我的问题提供一个很酷的解决方案。

【问题讨论】:

  • 不用担心,如果您发现拼写错误,您可以随时edit您的问题;)
  • list.push_back(&amp;x); 我们list的类型是什么?我们不知道SList 是什么,除了它不是 来自标准库。无论如何,推送一个自动变量的地址是一种巨大的代码味道,有些东西很远。
  • 您存储的是x 的地址,而不是它的值。变量永远不会移动,因此您始终存储相同的地址。
  • 请提供minimal reproducible example。理想情况下,不需要输入,例如带有硬编码的初始化。
  • 改用list.push_back(x);(可能适应SList的定义)

标签: c++ pointers memory-management


【解决方案1】:

在循环的每次迭代中,x = new char[i+1]; 返回一个不同的地址,该地址存储在x 中。所以x 在每次迭代中都会改变,而x地址 不会。

你是说

list.push_back(x);

添加新分配内存的地址?当然,这需要您将list 的类型更改为char * 的集合。


必须提到的是,在x 超出范围后取消引用&amp;x 将导致未定义的行为,因为x 不再存在。你用悬空指针填充list


最后我想提一下,您可以避免讨厌的手动内存管理,只需使用std::vector&lt;std::string&gt;

std::vector<std::string> list;

for (unsigned int i = 1; i < n+1; i++) {
    std::string newString(i, 'a'); // string with i times 'a'

    list.push_back(newString);
}

【讨论】:

    【解决方案2】:

    好的。我找到了一个非常简单的解决方案:

    char** x = new char*[n];
    SList sl;
    for (unsigned int i = 0; i < n; i++) {
    
        x[i] = new char[i+1];
        for (unsigned int j = 0; j < i; j++) {
            x[i][j] = 'a';
        }
        x[i][i] = '\0';
        sl.push_back(&x[i]);
    }
    

    具有 N 个地址来存储指向数组的指针。我可以将他们的地址添加到我的列表对象中

    【讨论】:

    • 仅供参考,&amp;x[i] 实际上就是x+i。并且您的x 最好与您的sl 一样至少 存在,并且在不再使用时正确清理,否则这仍然是内存泄漏和/或悬空指针的秘诀。我强烈怀疑无论 SList 是什么,为它的 push_back 需要一个指向 char 指针的指针本身就是一种代码味道,需要对这个神秘类进行更多的思考和调查。
    • 坦率地说,您找到了解决方法,而不是解决方案。根据您要在 s1 中存储的内容,您应该使用 std::string 和/或 std::array / std::vector 而不是添加更多 **
    • 确实如此。我看到了这个问题。泰
    • SList 只是 Common 单链表结构的包装器,它存储 char**
    • 您是否考虑过存储char** 的列表可能不一定是您任务的理想容器?例如,与其硬塞到与可能不合适的容器格式兼容的数据中,不如首先尝试使用更合适的容器。有了正确的容器和数据类型,C++ 可以让看似困难的问题变得异常简单,正如我希望我的 previous example 所展示的那样。
    猜你喜欢
    • 1970-01-01
    • 2013-09-04
    • 2016-02-19
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多