C++ non-const lvalue reference cannot bind to a temporary


1. 問題代碼

#include <iostream>
#include <vector>

//注意begin和end形參都聲明為引用
bool find_int(std::vector<int>::iterator &begin, std::vector<int>::iterator &end, int v){
    while(begin != end){
        if(*begin == v)
            return true;
        begin++;
    }
    return false;
}

int main(){
    std::vector<int> a(3, 100);
    //a.begin()和a.end()的返回值作為實參傳入find_int中
    std::cout << find_int(a.begin(), a.end(), 100) << std::endl;
}

2. 編譯錯誤

g++ -Wall -std=c++11 -o hello hello.cpp

編譯錯誤

3. 原因分析

non-const lvalue reference cannot bind to a temporary

根據編譯錯誤提示可以知道,不能將形參begin、end綁定到a.begin()和a.end()的返回值,因為該返回值是一個臨時量,臨時量的生命周期可能在a.begin()和a.end()執行完后就結束了。因此編譯器認為普通引用綁定一個臨時量,在find_int函數中可能會修改這個臨時量,然而此時臨時量可能已經被銷毀,從而導致一些未定義的行為,因此編譯器不允許將普通引用綁定到一個臨時量上。

4. 解決方案

  1. 將普通引用改為常量引用(PS:改為常量引用后不能修改綁定的對象,只能讀不能寫)
bool find_int(const std::vector<int>::iterator &begin, const std::vector<int>::iterator &end, int v)
  1. 修改函數的形參聲明,將引用改成普通變量
bool find_int(std::vector<int>::iterator begin, std::vector<int>::iterator end, int v)
  1. 用變量存儲a.begin()和a.end()的返回值
std::vector<int>::iterator begin = a.begin();
std::vector<int>::iterator end = a.end();
std::cout << find_int(begin, end, 100) << std::endl;

5. Tips

  1. 為什么方案一可行呢?通過常量引用綁定臨時量,臨時量就不會銷毀了嗎?
    1. C++標准:assigning a temporary object to the const reference extends the lifetime of this object to the lifetime of the const reference.
    2. 常量引用會延長臨時量的生命周期
  2. 普通引用只能綁定和引用類型相同的左值(PS:函數的返回值不是左值,因為無法對其進行賦值)
  3. 常量引用可以綁定臨時量、常量或者可轉換為引用類型的變量

6. 參考資料

  1. 常量引用綁定臨時量
  2. C++ primer 第五版-P55、P201


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM