Ros*_*oss 5 c c++ arrays pointers
我正在自学C++,因此一直在编写一些示例代码来真正指出我对指针和数组的理解.
我写了这个:
int myints[] = {20, 40, 60, 80, 100};
// C style array? should be stored on stack? is myint's type pointer to int or an array of int? how does it differ from myotherints?
int* myotherints = new int[5]{20, 40, 60, 80, 100}; // new always returns pointer, is this a C++ style array?
// does this pointer get created on stack while the elements themselves are created in free heap?
int j = 5; // should be stored on stack
cout << "myints: " << myints << endl; // decays to pointer, shows address array myints is stored at
cout << "*myints: " << *myints << endl; // myints decays to pointer and is dereferenced to return value stored at start of array myints
cout << "myints[0]: " << myints[0] << endl; // [] dereferences and returns value for element 0 (20)
cout << "myotherints: " << myotherints << endl; // some value?? this is totally unlike the others, why? what is this?
cout << "*myotherints: " << *myotherints << endl; // dereferences pointer myotherints to get address that holds value 20 for first element
cout << "myotherints[0]: " << myotherints[0] << endl; // [] dereferences pointer to get address that holds value 20 for first element
cout << "j: " << j << endl << endl; // 5, sure
cout << "&myints: " << &myints << endl; // array behaving as pointer, gives address of myints[0]
cout << "&myints[0]: " << &myints[0] << endl; // array behaving as pointer, gives address of myints[0]
cout << "&myotherints: " << &myotherints << endl; // address of myotherints, is this where the pointer to the array is stored?
cout << "&myotherints[0]: " << &myotherints[0] << endl; // [] dereferences the pointer that myotherints points to and returns element 0
cout << "&j: " << &j << endl; // address of j
/*
myints: 0x7fff096df830 <-- this makes sense to me, array decays to pointer to give first element address
*myints: 20 <-- this makes sense to me, dereference first element address for value
myints[0]: 20 <-- [] dereferences implicitly, returns value from pointer
myotherints: 0x2308010 <-- myotherints is a pointer to an array of ints, but its address is much lower compared to myints and j, why is that?
*myotherints: 20 <-- getting the value from above address returns 20
myotherints[0]: 20 <-- [] dereferences to address pointed to by pointer myotherints, returns value
j: 5
&myints: 0x7fff096df830 <-- same as below
&myints[0]: 0x7fff096df830 <-- same as above, meaning *myints and myints[0] are the same thing, this address
&myotherints: 0x7fff096df828 <-- how can the pointer to myotherints array be stored here when dereferencing it (*) returns 20 and...
&myotherints[0]: 0x2308010 <-- dereferencing this address with [] also returns 20, yet they are different memory locations unlike myints
&j: 0x7fff096df824
*/
Run Code Online (Sandbox Code Playgroud)
是不是说myint是一个"C风格数组",而myotherints是一个"C++风格数组"?
如果我理解正确,myotherints是一个指针但myints是一个数组,大多数时候表现得像一个指针?因此,虽然您可以使用myint进行指针处理,但有时候它不像指针那样,即使用&来显示其地址.这意味着myints与指针的类型不同.它的类型是"一系列的整数"吗?
存储myint(myins的东西,而不是其数组中的值),如果它总是自动解除引用数组存储的位置,我怎么能显示它的地址?与使用C++样式的新数组返回的指针不同?
这些在功能上以不同的方式表现在记忆中吗?
任何能够真正巩固我理解的文档提示或指示都将非常感激.谢谢!
Man*_*726 10
两者都是从C继承的东西(正确的C++数组的东西是std::array),但是你很困惑:
第一个是C数组,即具有静态/自动存储持续时间的事物,代表一块内存.该块的大小和"位置"(地址)在编译时确定.
第二个是一个指针到一个动态分配的内存块.换句话说,您使用指针将您请求的内存块的地址存储到OS.这对新手来说很困惑,因为这个东西有时被称为动态数组.C阵列不是一个相同意义上的数组,但实际上我们以相同的方式使用它们,但出于不同的目的.
关于C++:
C数组的行为类似于内存块的指针和一些含糖(数组索引等),因此它们总是通过引用传递(因为我们拥有的是通过值传递的地址,而不是数组本身),实际上它们会自动衰减在许多情况下指向.这些问题是std::array一个更好的选择,因为它具有正确的值语义并且没有隐式衰减.
在C++手册中应该避免内存管理,你应该使用标准库提供的容器(最着名的std::vector).C++语言提供自动,确定性和安全资源管理的功能; 包括内存资源.你应该使用这些.手动内存管理仅适用于非常低级别的编程和创建自己的资源管理处理程序.
C++从C语言中获得了类型衰减
在C中,有几种方法可以有效地使用整个数组.你不能把它们传递给函数,从函数返回它们,执行[]或==或者+他们至少直接或几乎所有的东西.
相反,每当你看到它有趣时,数组'衰变'到指向它的第一个元素的指针.(基本上,每当你在除了被视为实际数组的少数情况下使用它之外,它会衰减成指针).
所以arr[3]变成(&(first element of arr))[3]或*((&(first element of arr))+3)(这些意思是相同的).
当您return arr;将其传递给函数(在C中)时会发生类似的事情.你的cout << arr手段cout.operator<<( arr ),这只是一个功能.好吧,它也可能operator<<( cout, arr ).在C++中,您可以将对实际数组的引用传递给函数,但它需要一些工作并且不会在您的示例代码中发生.
如果你输入&arrdecay没有发生,你得到一个指向整个数组的指针.这很重要,因为指针算法,以及其他原因,以及数组数组如何以零开销工作. (&arr)+1指向数组的过去,不管它有多大 - ((&(arr[0]))+1)指向数组的第二个元素.
这是int arr[3]={4,5,6};有效的,或者int arr[]={4,5,6};(同样的 - 第二个只是3为你决定数字). arr在这两种情况下都是类型int[3].它int*容易衰变,但它是类型的int[3]. sizeof(arr)是三倍sizeof(int),而不是sizeof(int*).
当你new int[3],你没有得到一个指针int[3],而是你得到一个指针int[3]数组的第一个元素.从某种意义上说,它会被预先腐烂.这是指针的类型 - 数组的地址和第一个元素是相同的.但是类型信息(这是一个组合时间概念)不同!
它也存储在免费存储中,而不是自动存储(也就是堆和堆栈).但这不是根本区别.
C++唯一关于new int[3]你的东西new- 你可以malloc用来获取免费商店的数据空间,并获得一个指向第一个元素的指针int*.
听起来你对指针 v 数组的疑问比什么都多,但我会尝试并解决你所有的问题,
int myints[] = {20,40,60,80,100};
Run Code Online (Sandbox Code Playgroud)
C风格数组?
是的,这就是声明 C 风格数组的方式
这是在堆栈上吗?
是的,整个数组(所有 5 个变量)位于堆栈上,这意味着当其块超出范围时,数据本身也会超出范围,通过移动堆栈指针“释放”,这并不意味着您但无法使用&运算符创建指向该数组的指针以供其他函数使用。
这与 myOtherInts 有什么不同?
这是堆栈上的值,而 myotherints 是堆上的值,并且指针在堆栈上。
int* myOtherInts = new int[]{20,40,60,80,100};
Run Code Online (Sandbox Code Playgroud)
当元素本身在空闲堆中创建时,该指针是否在堆栈上创建?
是的,声明 anint*意味着您在堆栈上声明一个指针(指针而不是在堆栈上创建的值),并且当您将该变量分配给函数new返回的内容时(应该是在堆上分配的内存,必须释放它)稍后)你就有了一个指向堆存储值的堆栈存储指针。
cout << "&myotherints: " << &myotherints << endl;
Run Code Online (Sandbox Code Playgroud)
myotherints 的地址,这是存储数组指针的地方吗?
是的,这会返回内存中保存指向实际数据的指针的位置的地址,该地址与数据实际存储的位置不同。
//myotherints: 0x2308010 <-- myotherints is a pointer to an array of ints, but its address is much lower compared to myints and j, why is that?
Run Code Online (Sandbox Code Playgroud)
这里打印的值是存储数据的地址,与存储指针的位置不同。这个值低得多的原因是因为该内存所在的地址是由堆控制的,通常保存程序的低地址空间。
&myotherints: 0x7fff096df828 <-- how can the pointer to myotherints array be stored here when dereferencing it (*) returns 20 and...
&myotherints[0]: 0x2308010 <-- dereferencing this address with [] also returns 20, yet they are different memory locations unlike myints
Run Code Online (Sandbox Code Playgroud)
这有点棘手。回想一下,&运算符的意思是“给我地址”,因此要将您的代码翻译成英语,您有一点
give me the address of myotherints
Run Code Online (Sandbox Code Playgroud)
回想一下,myotherints 是您在堆栈上分配的指针,但是该指针指向堆上的内存。所以你应该期望得到一个看起来像是来自堆栈的值(即通常是一个更高的值)
give me the address of the first element of myotherints
Run Code Online (Sandbox Code Playgroud)
现在,再次myotherints是一个指向堆上值的指针,当您取消引用它时,[0]您将获得存储在堆上的第一个元素的值,因此当您询问存储在堆上的某些内容的地址时,您可以应该期望与存储在堆栈上的内容不同的结果。(即代表堆数据的相当低的数字)
编辑:对于真正的 C++ 分配数组的方法,您可能应该使用,std::array请参阅Manu 的答案