【问题标题】:dynamic memory allocation in C++ without pointers - what's the point of pointers?没有指针的 C++ 中的动态内存分配 - 指针的意义何在?
【发布时间】:2017-04-03 13:18:59
【问题描述】:

考虑以下 C++ 程序:

#include <iostream>
using namespace std;

void printArray(int p_values[], int size, int elements_set);

int main() 
{
    int next_element = 0;
    int size = 3;
    int p_values[size]; 
    int val;
    cout << "Please enter a number: ";
    cin >> val;

    while (val > 0)
    {
    if (size == next_element+1)
    {
        size *=2;
        int p_values[size];
    }
    p_values[next_element] = val;
    next_element++;
    cout << "Current array values are: " << endl;
    printArray(p_values, size, next_element);
    cout << "Please enter a number (or 0 to exit): ";
    cin >> val;
    }   

}


void printArray(int p_values[], int size, int elements_set) 
{
cout << "Total size of array: " << size << endl;
cout << "Number of slots set so far: " << elements_set << endl;
cout << "Values in the array: " << endl;
    for (int i = 0; i < elements_set; ++i){
        cout << "p_values[" << i << "] = "
             << p_values[i] << endl;
    }
}

代码的作用很简单: 1. 要求用户输入号码 2.数字保存在数组中 3.打印出当前数组的内容

一旦数组满了,它的大小就会加倍。 这种在运行时动态增加数组通常是用指针来完成的。 事实上,有人告诉我,只有使用指针才能动态增加数组大小。

但是,正如您在上面的程序中看到的那样,我没有使用任何指针,而只使用了一个静态数组。然而,程序会在运行时动态增加数组的大小。

因此,我的问题是: 1. 为什么我在大学(以及几本书中)被告知,在 C++ 程序中,在运行时增加内存使用量只能通过使用指针来实现? 2. 考虑到动态内存分配可以在没有指针的情况下完成,指针的意义是什么(除了可以在调用函数时通过引用传递变量)?

程序运行一段时间后,输入8个数字后,程序输出如下:

Please enter a number (or 0 to exit): 8
Current array values are: 
Total size of array: 12
Number of slots set so far: 8
Values in the array: 
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 8
Please enter a number (or 0 to exit): 

【问题讨论】:

  • 公平地说,这不是一个 C++ 程序。 VLA 不是 C++ 的一部分。
  • 指针用于指向事物。如何分配东西是另一回事。
  • 什么是 VLA,如果我可以问的话?
  • 它也不考虑范围。大括号内的 p_values 与 main 顶部的 p_values 不同,并且在其原始边界之外访问它是未定义的行为。简短的回答是“你没有这样做。”
  • 您不仅在使用 VLA,而且根本没有增加原始数组维度。您使用 VLA 定义了一个新的本地数组。您只是在通过旧数组的边界写入堆栈。无论哪种情况,迟早都会发生堆栈溢出

标签: c++ arrays pointers memory dynamic


【解决方案1】:
    size *=2;
    int p_values[size];
}

不。这不会增加在函数开头声明的现有p_values 数组的大小。这在内部范围内声明了一个名为 p_values 的不同数组...

...并且由于内部范围立即在此处结束,因此这没有任何效果。循环继续并在原始 p_values 数组的末尾运行,导致未定义的行为和内存损坏。

不过,程序会动态增加数组的大小 在运行时。

不,它没有。现有数组的大小没有动态增加。在内部范围内声明了一个不同的、更大的可变长度数组,并立即销毁。原始数组保持其原始大小,并导致未定义的行为。

只要继续向数组中输入更多的值,在某些时候你最终会破坏堆栈上的返回地址,导致main() 返回时出现段错误(假设你的编译器通过调整动态实现可变长度数组当前函数的堆栈帧的大小)。

【讨论】:

  • @Varshachik ...所以新数组的内存位置不是(!)旧数组的内存位置加上一些额外的内存?换句话说:新数组的第一个元素与旧数组的第一个值位于完全不同的内存位置? ...此外,旧数组使用的内存空间没有被释放,所以我的程序导致内存泄漏?
  • 不,这两个数组是完全独立的对象,彼此没有任何关系。此外,没有内存泄漏。新数组和旧数组的内存在它们各自的作用域终止时都会被释放,前提是没有发生未定义的行为。一旦发生未定义的行为,根据定义,结果是未定义的。
【解决方案2】:

您的代码不起作用。您的“重新分配”没有做任何事情 - 您正在创建另一个隐藏名称的数组。同时,您正在覆盖不属于您的内存(例如 p_values[9] 是存储大小变量的位置)。继续往下看,就更清楚了:

Please enter a number: 1
Current array values are:
Total size of array: 3
Number of slots set so far: 1
Values in the array:
p_values[0] = 1
Please enter a number (or 0 to exit): 2
Current array values are:
Total size of array: 3
Number of slots set so far: 2
Values in the array:
p_values[0] = 1
p_values[1] = 2
Please enter a number (or 0 to exit): 3
Current array values are:
Total size of array: 6
Number of slots set so far: 3
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
Please enter a number (or 0 to exit): 4
Current array values are:
Total size of array: 6
Number of slots set so far: 4
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
Please enter a number (or 0 to exit): 5
Current array values are:
Total size of array: 6
Number of slots set so far: 5
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
Please enter a number (or 0 to exit): 6
Current array values are:
Total size of array: 12
Number of slots set so far: 6
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
Please enter a number (or 0 to exit): 7
Current array values are:
Total size of array: 12
Number of slots set so far: 7
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
Please enter a number (or 0 to exit): 8
Current array values are:
Total size of array: 12
Number of slots set so far: 8
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 8
Please enter a number (or 0 to exit): 9
Current array values are:
Total size of array: 12
Number of slots set so far: 10
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 9
p_values[8] = 10
p_values[9] = 12
Please enter a number (or 0 to exit): 11
Current array values are:
Total size of array: 12
Number of slots set so far: 11
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 11
p_values[8] = 11
p_values[9] = 12
p_values[10] = 11
Please enter a number (or 0 to exit): 12
Current array values are:
Total size of array: 24
Number of slots set so far: 12
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 12
p_values[8] = 12
p_values[9] = 24
p_values[10] = 11
p_values[11] = 12
Please enter a number (or 0 to exit): 13
Current array values are:
Total size of array: 24
Number of slots set so far: 13
Values in the array:
Segmentation fault (core dumped)

【讨论】:

  • 新创建的数组不做任何事情,离开括号后被销毁
【解决方案3】:

事实上

int size = 3;
int p_values[size]; 

不是有效的 C++。这个特性(可变长度数组)是在 1999 年的标准中引入 C 的,并且不在任何 C++ 标准中,或者建议添加。一些 C++ 编译器(以及一些早于 1999 年 C 标准的 C 编译器)支持此功能作为非标准扩展。

即使我们假设编译器支持 C 的 VLA,这

int size = 3;
int p_values[size]; 

/* other code */
{
    size *=2;
    int p_values[size];
}

不调整p_values 的大小。它会暂时在嵌套范围内(即在{} 中)创建另一个不再存在于范围外的数组。

【讨论】:

  • 是的,我现在明白了……非常感谢大家的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 2015-05-19
  • 1970-01-01
  • 2021-04-15
  • 2019-03-17
  • 2018-08-11
相关资源
最近更新 更多