由重建二叉树算法题到临时对象不能绑定到非 const 的左值引用

前言

最近在刷剑指offer,在将一个临时变量传给一个引用的时候,出现了non-const lvalue reference to type 'vector<[...]>' cannot bind to a temporary of type 'vector<[...]>'的错误,意思就是不能将临时对象绑定到非const的左值的引用,那么在这里就总结一下这道算法题和const引用的用法。


const总结

对于一个const T&的初始值不一定是一个左值,甚至可以不是类型T,但是非const引用不能绑定非左值。
如下面的例子:

double *r1=3.14;//错误,3.14是一个临时变量,将引用r1绑定到临时变量上,可能发生r1引用修改临时变量的值。
const int *r2=3.14;//正确。

在初始化常量引用时,允许用任意表达式做出初始值,只要该表达式的结果能转换成引用的类型即可,同时,允许为一个常量引用绑定非常量的对象,字面值,甚至一个一般表达式。

int i=42;
const int &r1=i;//允许将const int& 绑定到一个普通的int对象上
const int &r2=42;//正确,r2是一个常量引用
const int &r3=r1*2;//正确,r3是一个常量引用
int &r4=r1*2;//错误,r4是一个非常量引用。

那么一个常量引用被绑定到另一种类型上到底发生了什么?看下面一个例子:

double dval=3.14;
const int &ri=dval;

其实等价于

const int temp=dval;
const int &ri=temp;

首先编译器首先会由双精度浮点数生成了一个临时的整形常量,然后让ri绑定这个临时变量。如何说明编译器不会让一个非const引用绑定到临时量呢?我们可以假设如果ri不是常量引用时,上面的初始化会发生什么?如果ri不是常量,那么就允许对ri赋值,这样就允许改变所引用对象的值。但是,此时绑定对象是一个临时量而非dval。既然想让ri引用dval,那么肯定想通过ri来改变dval的值,不然干嘛给ri赋值呢?所以编译器就认为将非常量引用绑定到临时量上是非法的行为。


算法题:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

基本思想是:
前序遍历的第一个元素就是根节点,在中序遍历中找到根节点值的位置,位于根节点值左边的值是二叉树的左子树,位于右边的值是二叉树的右子树,那么找到这些值再进行递归就可以重建二叉树了。

代码如下:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
         return reConstructCore(pre,vin);
    }
    //特别注意的就是函数的形参需要是const T&,不然在传实参的时候,如果实参是临时变量就会报错
    TreeNode* reConstructCore(const vector<int> &pre,const vector<int> vin)
    {
        if(pre.empty()) return NULL;
        int root_val=pre[0];
        TreeNode* root=new TreeNode(root_val);
        auto iter=find(vin.begin(),vin.end(),root_val);
        int left_num=iter-vin.begin();
        //这里传的实参是临时变量
        root->left=
 reConstructCore(vector<int(pre.begin()+1,pre.begin()+1+left_num),vector<int>(vin.begin(),vin.begin()+left_num));
       root->right=reConstructCore(vector<int>(pre.begin()+1+left_num,pre.end()),vector<int>(vin.begin()+left_num+1,vin.end()));
        return root;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章