【问题标题】:Dynamic memory allocation - C++动态内存分配 - C++
【发布时间】:2015-06-27 23:30:33
【问题描述】:

我正在自学 C++,目前正在学习动态分配内存。这是我目前正在使用的代码:

#include <iostream>

using namespace std;

int *memAdd(int* dyn_Point, int *lenPoint){
   int *new_Dyn_Point = new int[*lenPoint * 2];
   *lenPoint = *lenPoint * 2;
   for(int i = 0; i < *lenPoint; i++){
       new_Dyn_Point[i] = dyn_Point[i];
   }

   delete lenPoint;
   delete[] dyn_Point;
   return new_Dyn_Point;

}

int main(){

   int len = 2;
   int *lenPoint = &len;
   int current = 0;
   int val;
   int *dyn_Point = new int[len];


   cout << "Input a value for point 1: ";
   cin >> val;
   dyn_Point[current] = val;


   while(val > 0){
      current++;

      cout << "Input a value for point " << current+1 <<" (0 to exit): ";
      cin >> val;

      if(current+1 == len){
         *dyn_Point = *memAdd(dyn_Point, lenPoint);
         cout << len;
      }

      dyn_Point[current] = val;


   }

   for(int i = 0; i < len; i++){
     cout << &dyn_Point[i] << "\n";
     cout << dyn_Point[i] << "\n\n";

 }
 delete[] dyn_Point;

}

我的问题:当添加更多内存时,它是否必须增加某个值?

每当我的“len”变量中的值不是 2 时,我的程序将在我尝试分配更多内存或在分配更多内存并且必须第二次添加更多内存之后崩溃。

这是应该的样子还是我在这里完全遗漏了什么?

【问题讨论】:

  • 问题可能出在:while(val > 0){ current++;第一个 ++ 为当前提供 1,然后在 if 语句的检查中转到 current+1 以添加内存,因此只有当 len==2 时才添加内存。
  • 你复制的数据是你应该复制的两倍。这可能会导致崩溃。
  • 同样delete lenPoint 是错误的,因为它没有指向动态对象。
  • @NorbertvanNobelen 我不相信在那个领域会有问题。循环开始处的“current++”将其增加到 1,因为在循环开始之前填充了“dyn_Point[0]”。至于我的 if 语句中的“current+1”,这是我试图解决问题时遗留下来的,但对我所做的任何更改都没有实际影响
  • @MikeSeymour 我在哪里复制了我应该复制的两倍的数据,你能更清楚一点吗?此外,由于我对指针和动态对象还很陌生,所以我对删除东西有点过分热情,感谢您指出这一点。

标签: c++ memory dynamic-arrays dynamic-allocation


【解决方案1】:

您的 while 循环需要 break

while() {

    //do your steps
    break;
}

在函数memAdd 中需要进行以下更改:

// *lenPoint = *lenPoint * 2; 

// 上面一行需要注释,否则会导致溢出来影响循环条件:

    for(int i = 0; i < (*lenPoint-1); i++){

// 纠正for循环以解决溢出问题

下面的删除是不必要的,因为你没有分配内存 使用这个变量

// delete lenPoint;

对于您的问题:添加更多内存时是否必须增加某个值?

在这方面没有硬性规定。每当需要更多内存时,std::vector 将其大小(内存分配)加倍。它与您的方法略有不同。在达到分配的上限之前,您将内存翻倍。

**Edit**

根据 OP 请求编译完整代码

#include <iostream>

using namespace std;

int *memAdd(int* dyn_Point, int *lenPoint){
   int *new_Dyn_Point = new int[*lenPoint * 2];
  // *lenPoint = *lenPoint * 2;
   for(int i = 0; i < (*lenPoint-1); i++){
       new_Dyn_Point[i] = dyn_Point[i];
   }

   //delete lenPoint;
   delete[] dyn_Point;
   return new_Dyn_Point;

}

int main(){

   int len = 2;
   int *lenPoint = &len;
   int current = 0;
   int val;
   int *dyn_Point = new int[len];


   cout << "Input a value for point 1: ";
   cin >> val;
   dyn_Point[current] = val;


   while(val > 0){
      current++;

      cout << "Input a value for point " << current+1 <<" (0 to exit): ";
      cin >> val;

      if(current+1 == len){
         *dyn_Point = *memAdd(dyn_Point, lenPoint);
         cout << len<<"\n";
      }

      dyn_Point[current] = val;
     break;

   }

   for(int i = 0; i < len; i++){
     cout << dyn_Point[i] << "\n";
     cout << &dyn_Point[i] << "\n\n";

 }
 delete[] dyn_Point;

}

【讨论】:

  • break; 放在我的while 循环中只会在第一次迭代后结束它,不是吗?那真的对我没有任何帮助。注释掉 *lenPoint = *lenPoint * 2; 会阻止我使用变量来控制某些循环运行多长时间,因为 for(int i = 0; i &lt; 1; i++) 只会打印出 dyn_Point[0] 的值,然后循环就会结束。
  • @FutureWizard 您可以决定打破while循环的条件,否则它将以无限循环结束。你必须评论这一行 *lenPoint = *lenPoint * 2;但我更正了答案中的 for 循环条件,而不是硬编码。即使我们注释该行,该变量仍然可用。循环应该在打印第一个变量后结束,因为到目前为止在分配的内存中只插入了一个值
  • 你试过自己编译这段代码吗?它仍然无法正常工作,正如预期的那样,因为没有*lenPoint = *lenPoint * 2;,那么len 永远不会设置为超过2 使得for(int i = 0; i &lt; (*lenPoint-1);for(int i = 0; i &lt; 1; 完全相同也不需要设置中断条件,因为循环用户输入 0 时退出。
【解决方案2】:

“我的问题:当添加更多内存时,它必须增加某个值吗?”

当然,您必须使用这样的设计来管理内存分配。

特别是您应该遵守Rule of Three (Five),并在重新分配内存以增加到必要数量时复制所有现有元素。


比自己做所有事情(这可能容易出错)更好的选择是使用

std::vector<int> dyn_point;

和/或你班上的同类。

内存管理由container implementations负责,您无需为此烦恼。

【讨论】:

  • 非常感谢您的解释,我正在学习的这本书似乎没有使用vector 再写大约 50 页,所以我试图在没有它的情况下解决我的问题。
  • @FutureWizard 您可以从我提供给standard c++ container library 参考的链接中查看一些很好的参考和示例。遗憾的是,许多教科书、课程脚本和教程都试图将手动内存分配放在第一位。在实践中,你不应该有使用它的案例,而且它对于语言的高级使用来说是非常重要的东西,而不是初学者。
  • 公平地说,教科书并没有过多地手动分配内存。我认为在教他们一种更简单、更自动化的方法之前,让像我这样的初学者了解某些东西是如何工作的很重要。不过,从现在开始肯定会使用矢量。
  • @FutureWizard “不过,从现在开始肯定会使用矢量。” 好决定! :)(我很高兴拯救了另一个灵魂!你应该知道,I'm an evangelist of this opinion
  • @FutureWizard “教科书在手动分配内存方面并没有走得太远”这可能是因为从初学者的角度来说这很难教,而且它完全混淆了以下概念正确使用 RAII 和类实例化。如前所述,new/delete 不适合初学者,而是非常高级且很少使用的东西。
猜你喜欢
  • 1970-01-01
  • 2015-12-07
  • 2021-02-28
  • 2012-01-20
  • 1970-01-01
  • 2015-09-25
  • 2018-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多