c++函数的传参

前言

在阐述c++中函数传参之前,先说明一下为何写这篇博客。事实上,c++的传参方式的讨论已经很多,但是在解剑指 Offer 27. 二叉树的镜像(Leetcode 226翻转二叉树)时发现三种传参方式自己并没有完全弄清,在以树指针为对象时,就出现错误。

交换两个变量

网上有三种常见的交换变量的方式,第一种创建临时变量存储其中一个待交换的值,这种方法最为常见。

auto tmp = a;
a = b;
b = tmp;

第二种不创建临时变量,利用四则运算,代码如下,但是可能会产生数值溢出,不建议使用。

a = a + b;
b = a - b;
a = a - b;

第三种同样不创建临时变量,利用位运算,代码如下。这是因为 x ^ y ^ y = x,任意变量与其他变量异或两次结果等于自身。然而,该方法只适用于交换整型或者字符型数据交换,这是因为位运算的运算分量只能是这两者。

a = a ^ b;
b = a ^ b;
a = a ^ b;

所以,最简单的才是最有用的,第一种方法虽然朴素,但是有效。

问题描述

在翻转二叉树时,其实问题本身解答非常容易,Leetcode也是定级为简单。就是个普通的前序遍历或者后序遍历,前者自顶向下,后者自底向上。但是在交换两个TreeNode*变量时,自己写的交换函数竟不能通过。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root) return root;
        TreeNode* tmp = root->left;
        root->left = root->right;
        root->right = tmp;
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

自己的交换代码如下:

void swapNode(TreeNode* left, TreeNode* right){
    TreeNode *tmp = left; 
    left = right;
    right = tmp;
}

在invertTree函数中使用该函数,交换两个二叉树指针不能成功交换,而用c++自带的swap函数确又可以。

分析问题

函数传参有三种:值传递,引用传参和指针传参。三者的主要区别为:值传参只传递实参的拷贝值,函数中的操作不影响实参,引用传参和指针传参均会影响实参,函数执行完毕相当于实参完成了函数内部的操作。引用传参和指针传参的不用在于,引用传参必须要先初始化实参,而指针传参不必。以交换变量为例,三中传参分别为:

//值传参
void swap(int a,int b) {
	int tmp = a;
	a = b;
	b = tmp;
}
//引用传参
void swap(int &a,int &b) {
	int tmp = a;
	a = b;
	b = tmp;
}
//指针传参
void swap(int *a,int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

第一种不能完成实参的交换,后两种可以。这样分析下来,自己写的swapNode(TreeNode* left, TreeNode* right)函数看似也是指针传参呀,但是为何不行呢。这里就出现了偏差,TreeNode* 虽然是指针,但是被交换的两个变量也都是指针,相当于进行了值传参。如果想要真正让交换函数起到作用,应该进行引用传参或者指针传参。

解决方法

引用传参交换两个TreeNode*指针变量表示为:

void swapNode(TreeNode*& left, TreeNode*& right){
    TreeNode *tmp = left; 
    left = right;
    right = tmp;
}

如果有TreeNode* a和TreeNode* b,直接调用swapNode(a, b)即可。

指针传参交换两个TreeNode*指针变量表示为:

void swapNode(TreeNode** left, TreeNode** right){
    TreeNode *tmp = *left; 
    *left = *right;
    *right = tmp;
}

如果有TreeNode* a和TreeNode* b,直接调用swapNode(&a, &b)即可。

者两种传参方式传递树指针时,可能同时出现了**或者同时出现了*&略显怪异,但是事实确实如此。

如果有用请给我一个👍,转载注明出处:https://allentdan.github.io/

posted @ 2021-01-22 20:04  AllentBKY  阅读(492)  评论(0)    收藏  举报