由重建二叉樹算法題到臨時對象不能綁定到非 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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章