【important! 】An article to understand the passing of pointers as function parameters! If you don’t understand after reading this, hit me

Let’s talk about the most important conclusion first

When a pointer is passed into a function as a parameter, it is passed by value rather than by reference! ! !

Secondly, don't confuse pointers when they are defined with when they are used!

Define time/value p *p

**p

int p; //variable int variable
int *p; //One pointer address of int variable int variable
int **p; //double pointer The address of this memory of the address of the int variable address of int variable int variable
void function (int **p) //The parameter is a double pointer The address of this memory of the address of the int variable address of int variable int variable

for example:

The function is defined:

void function(int **p)

You may think: Yeah, this parameter is a double pointer, and **p represents a specific int value, so when using it, you may think of using it like this:

int a=10;
function(a);

wrong!

Because when defined, **p means that this is a double pointer, which is the address of an address.

When used, **P represents the value pointing to the variable itself.

Let’s write it simpler:

int a=10;
int *p=&a;
int **pp=&p;

When defined: **pp=&p=the address of pointer p

When used: **pp=a=10;

Although this is simple, it will cause a lot of difficulties in understanding. Don't get confused. If you get confused, come back and take a look!

Understand the passing of pointers as parameters (pointer actual parameters and formal parameters) through a simple piece of code

#include <bits/stdc++.h>
using namespace std;

void test(int *b)
{

cout << "形参指针地址:" << &b << endl;
cout << "形参指向内容:" << *b << endl;
cout << "实参和形参指向同一地址,但实参指针变量和形参指针变量自身地址不一致,可以看出传参方式为值传递而并非引用传递" << endl;
cout << endl;
cout << "==更改后==" << endl;
int num2 = 2;
b = &num2;
cout << "型参指向内容:" << *b << endl;
}

int main()
{
int num = 1;
int *a = &num;

cout << "==更改前==" << endl;

cout << "实参指针地址:" << &a << endl;
cout << "实参指向内容:" << *a << endl;
test(a);

cout << "实参指向内容:" << *a << endl;

return 0;
}

operation result:

==更改前==
实参和形参指向同一地址,但实参指针变量和形参指针变量自身地址不一致,可以看出为值传参而并非引用传参
实参指针地址:0x61fe10
形参指针地址:0x61fdf0
==更改后==
型参指向内容:2
实参指向内容:1

In short: pointer a and pointer b point to the same variable at the beginning, but the addresses of pointer a and pointer b themselves are different.

In the test function, pointer b points to other variables, so the modified content is not synchronized to the variable pointed to by pointer a.

That is, the test function parameters are passed by value.

If you want a more detailed understanding, refer to the blog: A good blog for understanding pointer passing parameters.

Let’s look at the actual application through the questions of 1161 Binary Tree Traversal (it is recommended to take a look, simple questions, not complicated)

Question link

My solution

This is the version I originally wrote:

//根据二叉树的前序遍历字符串,构建树,并输出中序遍历结果
#include <bits/stdc++.h>
using namespace std;

string s;
int len;

//定义二叉树的节点
struct node
{
char c;
node *left;
node *right;
};

void createTree(node *root)
{
if (len >= s.length())
return; //到最后一个字符了,结束返回(字符串最后3个字符一定是###)
char c = s[len++];
if (c == '#')
{
root = NULL;
return;
}
else
{
root = new node;
root->c = c;
//左右孩子初始化
root->left = NULL;
root->right = NULL;
//因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
createTree(root->left);
createTree(root->right);
}
}

void midOrdTrave(node *node)
{
//中序遍历
if (node != NULL)
{
midOrdTrave(node->left);
cout << node->c << " ";
midOrdTrave(node->right);
}
return;
}

int main()
{
while (cin >> s)
{
node *binaryTreeRoot=NULL;
len = 0;
createTree(binaryTreeRoot);
midOrdTrave(binaryTreeRoot);
cout << endl;
}

return 0;
}

Segment fault was reported when compiling, and runtime error was reported when submitting.

It is not difficult to know that the pointer accessed the memory space that should not be accessed.

Later, I found out that it was because in the main function, binaryTreeRoot was still NULL after going through createTree. Why is this?

After reading the above content, you will understand that the error lies in the parameter passing of the createTree function. The formal parameter root of the createTree function points to a new memory address when the new node is created. At this time, the actual parameter binaryTreeRoot has not changed and still points to NULL. Therefore, if you perform in-order traversal later, an error will definitely be reported.

At this time, when we pass parameters, because what we need to operate is the actual parameter pointer passed in , not the formal parameter pointer , we need to pass in the address of the binaryTreeRoot pointer (the same as the classic swap example), in order to It has a real two-way data binding effect, that is:

int main()
{
while (cin >> s)
{
node *binaryTreeRoot = NULL;
len = 0;
createTree(&binaryTreeRoot);

midOrdTrave(binaryTreeRoot);
cout << endl;
}

return 0;
}

At this time, the parameter received by createTree is the address of the address , which is equivalent to a double pointer , so certain modifications need to be made when defining the formal parameters, namely

//建树
void createTree(node **root)

When used within this function, **root is the pointed node, *root is the pointer to the node, and root is the address of the pointer.

When we modify the node content, we should update it using (*root->c=new_char). But using it directly will report a compilation error, so we use a tmp pointer to overdo it.

//创建一个新节点
node *tmp = new node;
tmp->c = c;
tmp->left = NULL;
tmp->right = NULL;

*root = tmp;

//因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
createTree(&(tmp->left));
createTree(&(tmp->right));

The same goes for the recursion in the last two lines.

Then the complete updated code is as follows (you can also see the solution, the same):

//根据二叉树的前序遍历字符串,构建树,并输出中序遍历结果
#include <bits/stdc++.h>
using namespace std;

string s;
int len; //每次遍历到的字符串中字符的index

//定义二叉树的节点
struct node
{
char c;
node *left;
node *right;
};

//建树
void createTree(node **root)
{
if (len >= s.length())
return; //到最后一个字符了,结束返回(字符串最后3个字符一定是###)
char c = s[len++];

if (c == '#')
{
*root = NULL;
return;
}
else
{
//创建一个新节点
node *tmp = new node;
tmp->c = c;
tmp->left = NULL;
tmp->right = NULL;

*root = tmp;

//因为字符串s是线序遍历,所以这里根据先序遍历的顺序构造树
createTree(&(tmp->left));
createTree(&(tmp->right));
}
}

void midOrdTrave(node *node)
{
//中序遍历
if (node != NULL)
{
midOrdTrave(node->left);
cout << node->c << " ";
midOrdTrave(node->right);
}
return;
}

int main()
{
while (cin >> s)
{
node *binaryTreeRoot = NULL;
len = 0;
createTree(&binaryTreeRoot);

midOrdTrave(binaryTreeRoot);
cout << endl;
}

return 0;
}

Let’s review the two key points

  • When a pointer is passed into a function as a parameter, it is passed by value rather than by reference.
  • Distinguish the difference between pointer (or *) when it is defined and when it is used, do not confuse it

After understanding this document, you will basically not have too many difficulties with future pointers!

Guess you like

Origin blog.csdn.net/zhong233/article/details/126229075