有什么区别?指向数组与常规数组的指针

Whats the difference? Pointer to an array vs regular array

本文关键字:数组 常规 指针 什么 区别      更新时间:2023-10-16

我熟悉Java,并试图自学C/C++。我正在从一个在这里托管他们的材料的班级中窃取一些课程。不幸的是,我不能问老师,因为我不在课堂上。我关心的是"动态声明的数组"下的部分:

如果你 希望能够更改大小 运行时的数组,然后声明 动态数组。这些是用 指针和新运算符。对于 指针基础知识,请阅读指针 部分。

使用新的分配内存,然后 您以相同的方式访问阵列 您将是一个静态数组。例如

int* arrayPtr = new int[10]; 为 (int i = 0; i <10; i++({ arrayPtr[i] = i; }

内存图片与 静态数组,但您可以更改 如果需要,可以调整大小。不要忘记你 必须在之前释放内存 分配新内存(否则您将 有内存泄漏(。

删除 [] 数组Ptr; 的 [] 删除数组指针时需要 arrayPtr = new int[50]; . . .

当您完全完成 数组,则必须删除其内存:

删除 [] 数组Ptr;

动态多维数组是 以与Java类似的方式完成。你 将具有指向指针的指针。对于一个 示例,请参阅

我的理解是,C 中的数组只是对数组中第一个元素的内存地址的引用。

那么,如果有的话,int *pointerArray = new int[10];int array[10];有什么区别呢?

我做过一些测试,似乎表明它们做完全相同的事情。是网站错了还是我看错了?

#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
    // Initialize the pointer array
    int *pointerArray = new int[10];
    for (int i = 0; i < 10; i++){
        pointerArray[i] = i;
    }
    // Initialize the regular array
    int array[10];
    for (int i = 0; i < 10; i++){
        array[i]= i;
    }
    cout << *(pointerArray + 5) << endl;
    cout << *(array + 5) << endl;
    cout << pointerArray[5] << endl;
    cout << array[5] << endl;
    cout << pointerArray << endl;
    cout << array << endl;
    return 0;
}

输出:

5
5
5
5
0x8f94030
0xbfa6a37c

我试图按照网站上的描述"动态调整"我的指针数组的大小,但我的新(更大的(指针数组最终填充了 0,这不是很有用。

int array[10];静态声明数组大小,这意味着它是固定的 - 这是唯一的主要区别。它也可以被分配到函数的堆栈帧内,即在程序的堆栈上。您无需担心在这种数组上使用delete [],实际上,如果您delete它,您可能会使程序崩溃。

当您使用 operator new 时,您可以动态分配内存,这可能会更慢,并且内存通常来自而不是程序的堆栈(尽管并非总是如此(。在大多数情况下,这更好,因为堆栈空间比堆空间更受限制。但是,您必须注意内存泄漏,并在不再需要时delete[]您的东西。

至于你的数组被零填充,你的类材料没有说你必须这样做:

int *arr = new int[20]; // old array
//do magic here and decide that we need a bigger array
int *bigger = new int[50]; // allocate a bigger array
for (int i = 0; i < 20; i++) bigger[i] = arr[i]; // copy the elements from the old array into the new array
delete[] arr;
arr = bigger;

该代码将数组arr扩展了 30 多个元素。请注意,您必须将旧数据复制到新数组中,否则它将不存在(在您的情况下,一切都变为 0(。

我的理解是,C 中的数组只是对数组中第一个元素的内存地址的引用。

那么,int *pointerArray = new int[10]; 和 int array[10]; 如果有的话,有什么区别?

您提到的是任何C/C++初学者都感到困惑的原因。

在 C/C++ 中,数组对应于一个足够大的内存块,可以容纳其所有元素。这与[]语法相关联,如您的示例所示:

int array[10];

C/C++ 的一个功能是,您可以使用指向数组类型的指针来引用数组。因此,您可以编写:

int* array_pointer = array;

这与:

int* array_pointer = &array[0];

这允许以通常的方式访问数组元素:array_pointer[3],但是你不能把array当作一个指针,就像对它做指针算术一样(即,array++惨败(。

也就是说,您也可以在不使用[]语法的情况下管理数组,只需使用 malloc 分配数组,然后将它们与原始指针一起使用。这就造就了C/C++的"美"。

恢复:指针和它指向的内存(实际数组(之间必须有区别:

  1. 声明中的[]语法(即int array[10];(同时引用这两个方面(它给你,比如说,一个指针和一个数组(;

  2. 当声明一个指针变量(即int* p; (,你只得到指针;

  3. 当计算表达式(即int i = p[4];array[4];(时,[]只是意味着取消引用指针。

除此之外,int *pointerArray = new int[10];int array[10]; 之间的唯一区别是前者是动态分配的,后者在堆栈上。

动态分配:

int * pointerArray = new int[10]; 

[顺便说一句,这是一个指向 10 个整数数组的指针,而不是指针数组]

静态分配(可能在堆栈上(:

int array[10]; 

否则它们是相同的。

当来自 Java 时,理解 C/C++ 数组的问题在于 C/C++ 区分数组变量和用于存储数组内容的内存。这两个概念都很重要且不同。在 Java 中,你实际上只是对数组对象的引用。

您还需要了解 C/C++ 有两种分配内存的方法。可以在帮助或堆栈上分配内存。Java没有这种区别。

在 C 和 C++ 中,数组变量是指向数组第一个元素的指针。数组变量可以存在于堆或堆栈上,包含其内容的内存也可以存在。它们可以是不同的。您的示例是int数组,因此您可以将数组变量视为int*

int *pointerArray = new int[10];int array[10];之间有两个区别:

第一个

区别是包含第一个数组内容的内存是在上分配的。第二个数组更棘手。如果 array 是函数中的局部变量,则其内容在堆栈上分配,但如果它是类的成员变量,则其内容将在分配包含对象(堆或堆栈(的任何位置分配。

第二个区别是,正如您已经意识到的,第一个数组是动态的:它的大小可以在运行时确定。第二个数组是固定的:编译器必须能够在编译时确定其大小。

首先,我会找其他地方来学习C++。 您引用的页面是非常混乱,与实际编程的方式无关在C++。 在C++中,大多数时候,你会将std::vector用于数组,而不是您引用的页面上提出的复杂解决方案。 在实践中,您从不使用operator new[](数组new(。

事实上,std::vector在某些方面更像是ArrayList而不是简单。Java 中的数组;与 Java 中的数组不同,您可以简单地增加向量通过将元素插入其中,最好在末尾。 它支持迭代器,尽管C++迭代器与 Java 有很大不同迭代器。 另一方面,您可以使用[]访问它运算符,就像普通数组一样。

您引用的页面上描述的数组通常称为 C 样式阵 列。 在C++,它们的使用主要限于具有静态的对象一生,尽管它们偶尔会出现在课堂上。 在任何情况下,它们都不会动态分配。

主要区别在于,数组不允许对指针执行某些操作。

一方面:

int ar[10];

正在使用堆栈上分配的内存。你可以认为它在本地也可用,虽然可以将指针/引用传递给其他函数,但一旦内存超出范围,内存就会被释放(在你的例子中,在 main 方法的末尾,但通常不是这种情况(。

另一方面:

int ar* = new int[10];

为堆上的数组分配内存。它可用,直到您的整个程序退出或使用以下命令删除它

delete[] ar;

请注意,对于删除,您需要"[]"当且仅当相应的新人也有它们时。

有区别,但不是在你指向的区域。 *pointerArray将指向大小为 10 字节的内存块的开头。array也是如此.唯一的区别是它在内存中的存储位置。 pointerArray 是动态分配的内存(在 run-time 处(,因此将进入堆,而array[10]将在 compile-time 处分配并进入堆栈。

确实,您可以通过使用指向其第一个元素的指针来获取大多数数组功能。但是编译器知道静态数组由多个元素组成,最显着的区别是sizeof运算符的结果。

sizeof(pointerArray) = sizeof int*

sizeof(array) = 10 * sizeof int