C++ 理解C++;指针(当它们指向指针时)

C++ 理解C++;指针(当它们指向指针时),c++,memory,pointers,C++,Memory,Pointers,我想我很了解参考资料和指针。以下是我(认为我)知道的: 请随时评论或更正这些陈述 现在我尝试跳转到指针数组。以下是我不知道的: char **char_ptrs = new char *[50]; Node **node_ptrs = new Node *[50]; 我的理解是,我有两个指针数组,一组指向字符的指针和一组指向节点的指针。因此,如果我想设置值,我会这样做: char_ptrs[0] = new char[20]; node_ptrs[0] = new Node; 现在我有一个指

我想我很了解参考资料和指针。以下是我(认为我)知道的:

请随时评论或更正这些陈述

现在我尝试跳转到指针数组。以下是我不知道的:

char **char_ptrs = new char *[50];
Node **node_ptrs = new Node *[50];
我的理解是,我有两个指针数组,一组指向字符的指针和一组指向节点的指针。因此,如果我想设置值,我会这样做:

char_ptrs[0] = new char[20];
node_ptrs[0] = new Node;
现在我有一个指针,在数组的0位置,在每个数组中。同样,如果我感到困惑,请在这里随意评论


那么,**操作符做什么?同样,在实例化旁边放一个*做什么(*[50])?(具体叫什么,实例化?

***
只是
*
两次,所以指针指向指针


当放在类型旁边时,
*
绑定左侧,而不是右侧。说
newchar*[50]
实际上是
newchar*[50]
并实例化了一个由50个
char*

组成的数组。在第一个代码块中所做的陈述都是正确的

char **char_ptrs = new char *[50];
…表示您有一个50个字符的数组

你对我的评价

char_ptrs[0] = new char[20];
node_ptrs[0] = new Node;
这也是正确的

**
仅表示“指向指针的指针”。不是接线员

当你写作时

new char *[50];
…您说的是“为50个字符分配存储空间”。

一些评论:

*ptr = 10; // Doesn't need to "go get" the value. Just overwrites it.
此外:

更容易认为您有两个数组。然而,从技术上讲(就编译器而言),您拥有的是两个指针。一个是指向字符的指针,另一个是指向节点的指针

这很容易从变量的声明中看出,顺便说一下,从右到左最容易读取:

char **char_ptrs
从右到左阅读:
char\u ptrs
是指向
char

将*放在指针旁边正确地称为取消对该指针的引用。由于数组在技术上不存在,数组上的运算符[]也是一种解引用操作:
arr[i]
是另一种写入
*(arr+i)
的方法。要正确理解这一点,您需要熟悉

多个连续的*s:每个*s都取消引用其操作的表达式的结果。因此,在写作时:

char c = **char_ptrs;
发生的情况是:

char\u ptrs
是指向char的指针。取消引用一次(对于最右边的*)可以得到它的值,即指向字符的指针。取消引用该值(对于最左边的*)会依次给出它自己的值,即char。最后,
c
包含存储在内存中的char值,该值位于char_ptrs所指向的指针(换句话说,数组中的第一个指针)指向的位置


相反,如果您编写
**char_ptrs='a'然后更改该内存位置中的值。

澄清第一部分:

int i = 5; // i is a primitive type, the value is 5, the address is retrieved via &i.
int *ptr;  // an unassigned pointer to an int
ptr = &i;  // ptr now point to the address of variable i
*ptr = 10; // access (dereference) the value through ptr and change it to 10 (same as i=10)
没有**操作符,只有*操作符。正如其他人所说,**声明指向指针的指针。因为您正在声明指针数组,并且指针是用*运算符声明的,所以在使用
new
为指针分配内存时,需要这样声明它们。因此,你必须:

char **char_ptrs = new char *[50]; // allocates memory for 50 contiguous char* (pointers)
Node **node_ptrs = new Node *[50]; // allocates memory for 50 contiguous Node* (pointers)
指向指针的指针不一定要声明数组。您也可以让另一个指针指向一个常规指针,如:

char i = 'p';
char *myptr = &i;
char **mysecondptr = &myptr;

如果您发现*符号难以阅读,请使用typedef帮助使代码易于阅读

typedef char*      CharPtr;
typedef CharPtr*   CharPtrPtr;
// Alternative to the line above
// typedef char**     CharPtrPtr;

// When you call new. You get a ptr to the type you are newing.
// new int returns an intPtr. new char returns a charPtr
CharPtrPtr char_ptrs = new CharPtr[50];

// So new CharPtr returns a CharPtrPtr
// In this case we return a pointer to contigious
// chunk of memory large enough to hold 50 CharPtr objects.

*ptr=10不是“获取存储在ptr中的值并将其更改为10”。它应该是“转到ptr中的值,使用它找到另一个位置,并在那里存储10”。这就是取消对指针的引用的意义。@Uri非常符合。编辑和更新。我应该注意到这本书对学习C语言中的指针非常有帮助:理解和使用Richard Reese的C指针。我会向任何学习C或C++的人推荐这一点,因为它的概念是无价之宝。有时语法会让人困惑。我更喜欢用“char**char_ptrs=new char*[50];”来明确它,但这也有它的缺点。不,不要。隐藏某个东西是指针的事实是非常糟糕的风格,伊姆霍。在一般情况下,我同意尼尔的观点。但是Ptr是好的,因为你没有隐藏它(IMHO)。但由于这是一个学习练习,只是为了习惯使用指针,所以它是有效的。当你像我一样变老变懒的时候,an Niel的*同样容易阅读,打字也更快:-)我认为Jon在这里赢得了认可。感谢伊格纳西奥,因为你的回答直截了当,切中要害。谢谢。出于教育目的,你的问题很好,所以我也提出了+1。我认为我还应该推广我提到的RTL阅读技巧,因为它非常有用:
const char*
char*const
?:-)
char i = 'p';
char *myptr = &i;
char **mysecondptr = &myptr;
typedef char*      CharPtr;
typedef CharPtr*   CharPtrPtr;
// Alternative to the line above
// typedef char**     CharPtrPtr;

// When you call new. You get a ptr to the type you are newing.
// new int returns an intPtr. new char returns a charPtr
CharPtrPtr char_ptrs = new CharPtr[50];

// So new CharPtr returns a CharPtrPtr
// In this case we return a pointer to contigious
// chunk of memory large enough to hold 50 CharPtr objects.