簡體   English   中英

返回非常量左值引用

[英]Returning non-const lvalue reference

我正在嘗試使用《 交互式計算機圖形學-自上而下的方法》這本書來學習計算機圖形學,示例代碼在此鏈接中

有一個名為“ mat.h”的標頭庫,提供了一些矩陣實用程序,但是當我嘗試使用Xcode進行編譯時,會引發以下錯誤:

類型為“ Angel :: mat2”的非常量左值引用不能綁定到類型為“ Angel :: mat2”的臨時對象

引發該錯誤的代碼是:

mat2& operator /= ( const GLfloat s ) {
#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        return mat2();
    }
#endif // DEBUG

我只是將其注釋掉,因為它只是在調試應用程序時編譯的,但是我想知道問題出在哪里以及如何解決。

嚴格地說,而正式的原因錯誤是綁定一個非const引用到一個臨時的嘗試,這里真正的問題是要試圖返回一個引用任何引用到臨時對象。 引用是否為const無關緊要。

return語句完成后,臨時對象將立即銷毀,從而導致綁定到當前已銷毀對象的懸掛引用。 換句話說,即使我們嘗試通過將返回類型更改為const reference來“修復”此代碼,它仍然無法正常工作。

而且,似乎設計上該函數應該返回非常量引用,這意味着更改此函數的返回類型不是一種選擇。 非常量引用是復合賦值運算符通常返回的內容。 在“被零除”的情況下,調試分支只應提早終止(當然,還可以返回任何東西,僅僅是為了編譯代碼)。

實現的一個方法是聲明類型的一個獨立的對象mat2 (如類的靜態成員mat2 ,例如),並返回對它的引用。 即聲明

class mat2 {
  ...
#ifdef DEBUG
  static mat2 bad_result;
#endif // DEBUG
};

定義它

#ifdef DEBUG
mat2 mat2::bad_result;
#endif // DEBUG

然后做

return bad_result;

每當檢測到錯誤時。

另外(更容易),您可以在該return語句之前在本地聲明它

#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        static mat2 bad_result;
        return bad_result;
    }
#endif // DEBUG

當然,這種設計存在明顯的缺陷,因為外部代碼將能夠修改返回的對象,這是不希望的。 但是,最有可能的想法是,一旦將錯誤消息打印到std::err ,就不能保證程序的行為,這意味着在這種情況下,返回值的可修改性應該不成問題。

考慮到最后一點,我們甚至可以使用非靜態局部變量作為返回值

#ifdef DEBUG
    if ( std::fabs(s) < DivideByZeroTolerance ) {
        std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] "
                  << "Division by zero" << std::endl;
        mat2 bad_result;
        return bad_result;
    }
#endif // DEBUG

返回對局部變量的引用與返回對臨時變量的引用是錯誤的(出於大致相同的原因)。 但是,在“錯誤后無保證”的方法內,它將“起作用”,這意味着它將修復錯誤消息。

問題在於,非const左值引用不能綁定到臨時值rvalue 只有const左值引用(在C ++ 98和C ++ 11中)或右值引用(僅在C ++ 11中)可以。 該運算符試圖返回對從函數返回時創建的臨時對象的左值引用:

    mat2& operator /= ( const GLfloat s ) {
//  ^^^^^
//  RETURNS A NON-CONST LVALUE REFERENCE
        ...
        return mat2(); // <--- CREATES A TEMPORARY (RVALUE)
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM