有什么不同? 指向数组与常规数组的指针
我熟悉Java并试图自学C / C ++。 我正在从一个托管他们材料的课程中窃取一些课程。 不幸的是,我不能问老师,因为我不在课堂上。 我关注的是“动态声明的数组”下的部分:
如果希望能够在运行时更改数组的大小,则声明动态数组。 这些都是通过指针和new运算符完成的。 有关指针的基础知识,请阅读指针部分。
使用new分配内存,然后以与静态数组相同的方式访问数组。 例如,
int * arrayPtr = new int [10]; for(int i = 0; i <10; i ++){arrayPtr [i] = i; }
内存画面与静态数组相同,但您可以根据需要更改大小。 不要忘记在分配新内存之前必须释放内存(否则会导致内存泄漏)。
delete [] arrayPtr; //删除数组指针时需要[] arrayPtr = new int [50]; 。 。 。
完成数组后,必须删除其内存:
delete [] arrayPtr;
动态多维数组以与Java类似的方式完成。 你将有指针指针。 例如,请参阅a
我的理解是C中的数组只是对数组中第一个元素的内存地址的引用。
那么, int *pointerArray = new int[10];
之间的区别是什么int *pointerArray = new int[10];
和int array[10];
如果有的话?
我做了一些测试,似乎表明他们完全一样。 网站是错的还是我读错了?
#include #include 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数组[10]; 如果有的话?
你提到的是在任何C / C ++初学者中引起很多混淆的原因。
在C / C ++中,数组对应的存储块足够大以容纳其所有元素。 这与[]
语法相关联,如您的示例中所示:
int array[10];
C / C ++的一个特性是你可以通过使用指向其类型的指针来引用数组。 因此,您可以写:
int* array_pointer = array;
这与:
int* array_pointer = &array[0];
这允许以通常的方式访问数组元素: array_pointer[3]
,但你不能将array
视为指针,就像在它上面做指针算术(即数组++悲惨地失败)。
也就是说,你可以在不使用[]
语法的情况下管理数组,只需使用malloc
分配数组,然后将它们与原始指针一起使用即可。 这就是C / C ++的“美”。
恢复:必须区分指针和它指向的内存(实际数组):
-
声明中的
[]
语法(即int array[10];
)同时引用这两个方面(它给出了一个指针和一个数组); -
当声明一个指针变量(即
int* p;
)时,你只需得到指针; -
在计算表达式时(即
int i = p[4];
或array[4];
),[]
仅表示解除引用指针。
除此之外, int *pointerArray = new int[10];
之间的唯一区别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];
:
第一个区别是包含第一个数组内容的内存在堆上分配。 第二个arrays更棘手。 如果array
是函数中的局部变量,那么它的内容将在堆栈上分配,但如果它是类的成员变量,则在分配包含对象(堆栈或堆栈)的任何位置分配其内容。
第二个区别是,正如您所知,第一个数组是动态的:它的大小可以在运行时确定。 第二个数组是固定的:编译器必须能够在编译时确定其大小。
首先,我会寻找其他一些学习C ++的地方。 您引用的页面非常混乱,与实际使用C ++编程的方式几乎没有关系。 在C ++中,大多数情况下,您将std::vector
用于数组,而不是您引用的页面上提出的复杂解决方案。 实际上,您从不使用operator new[]
(数组new
)。
实际上, std::vector
在某些方面比Java中的简单数组更像ArrayList
; 与Java中的数组不同,您可以通过在其中插入元素来简单地增长矢量,最好是在最后。 它支持迭代器,尽管C ++迭代器与Java迭代器有很大不同。 另一方面,您可以使用[]
运算符访问它,就像普通数组一样。
您引用的页面上描述的数组通常称为C样式数组。 在C ++中,它们的使用主要限于具有静态生命周期的对象,尽管它们偶尔会出现在类中。 无论如何,它们永远不会动态分配。
主要区别在于数组上不允许指针允许的某些操作。
一方面:
int ar[10];
正在使用堆栈上分配的内存。 您可以将其视为本地可用,并且可以将指针/引用传递给其他函数,一旦内存超出范围,内存将被释放(在主示例结尾的示例中,但通常是不是这样)。
另一方面:
int ar* = new int[10];
为堆上的数组分配内存。 它可用,直到您的整个程序退出或使用它删除
delete[] ar;
请注意,对于删除,您需要“[]”当且仅当相应的新用户也拥有它们时。
你指出的区域有区别,但没有区别。 *pointerArray
将指向大小为10个字节的内存块的开头。 array
。 唯一的区别是它存储在内存中的位置。 pointerArray
是动态分配的内存(在run-time
),因此将进入堆,而array[10]
将在compile-time
分配并将进入堆栈。
确实,您可以通过使用指向其第一个元素的指针来获得大多数数组function。 但是编译器知道静态数组由几个元素组成,最显着的区别是sizeof
运算符的结果。
sizeof(pointerArray) = sizeof int*
sizeof(array) = 10 * sizeof int