[英]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.