简体   繁体   English

返回非常量左值引用

[英]Returning non-const lvalue reference

I am trying to learn computer graphics using the book Interactive computer graphics - A top-down approach , the code of the examples is in this link 我正在尝试使用《 交互式计算机图形学-自上而下的方法》这本书来学习计算机图形学,示例代码在此链接中

There's a header library called ´mat.h´ that gives some matrix utilities, but when I try to compile with Xcode the following error is thrown: 有一个名为“ mat.h”的标头库,提供了一些矩阵实用程序,但是当我尝试使用Xcode进行编译时,会引发以下错误:

Non-const lvalue reference to type 'Angel::mat2' cannot bind to a temporary of type 'Angel::mat2' 类型为“ Angel :: mat2”的非常量左值引用不能绑定到类型为“ Angel :: mat2”的临时对象

The piece of code that throws that error is: 引发该错误的代码是:

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

I just comment it out because it just gets compiled when debugging the app, but I would like to know what's the problem and how to solve it. 我只是将其注释掉,因为它只是在调试应用程序时编译的,但是我想知道问题出在哪里以及如何解决。

Strictly speaking, while the formal reason for the error is the attempt to bind a non-const reference to a temporary, the real problem here is the very attempt to return a reference , any reference to a temporary object. 严格地说,而正式的原因错误是绑定一个非const引用到一个临时的尝试,这里真正的问题是要试图返回一个引用任何引用到临时对象。 Whether the reference is const or not does not matter. 引用是否为const无关紧要。

The temporary object will be destroyed right after the return statement completes, resulting in a dangling reference bound to a now-destroyed object being returned. return语句完成后,临时对象将立即销毁,从而导致绑定到当前已销毁对象的悬挂引用。 In other words, even if we attempt to "fix" this code by changing the return type to const reference, it still won't work properly. 换句话说,即使我们尝试通过将返回类型更改为const reference来“修复”此代码,它仍然无法正常工作。

Moreover, it appears that by design this function is supposed to return a non-const reference, meaning that changing the return type of this function is not an option. 而且,似乎设计上该函数应该返回非常量引用,这意味着更改此函数的返回类型不是一种选择。 A non-const reference is what compound assignment operators typically return. 非常量引用是复合赋值运算符通常返回的内容。 The debug branch is just supposed to terminate early (and, of course, to return something, anything just to make the code compile) in case of "divide by zero" situation. 在“被零除”的情况下,调试分支只应提早终止(当然,还可以返回任何东西,仅仅是为了编译代码)。

One way to achieve that is to declare a standalone object of type mat2 (as a static member of class mat2 , for example) and return a reference to it. 实现的一个方法是声明类型的一个独立的对象mat2 (如类的静态成员mat2 ,例如),并返回对它的引用。 Ie declare 即声明

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

define it 定义它

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

and then do 然后做

return bad_result;

whenever an error is detected. 每当检测到错误时。

Alternatively (and much more easily) you can declare it locally right before that return statement 另外(更容易),您可以在该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

Of course, there's an obvious flaw in this design, since the outside code will be able to modify the returned object, which is undesirable. 当然,这种设计存在明显的缺陷,因为外部代码将能够修改返回的对象,这是不希望的。 However, most likely the idea is that the program's behavior is not guaranteed once an error message is printed to std::err , meaning that the modifiability of the returned value should not be a problem in this case. 但是,最有可能的想法是,一旦将错误消息打印到std::err ,就不能保证程序的行为,这意味着在这种情况下,返回值的可修改性应该不成问题。

Taking that last point into account, we can even use a non-static local variable as a return value 考虑到最后一点,我们甚至可以使用非静态局部变量作为返回值

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

To return a reference to a local variable is as wrong as to return a reference to a temporary (for largely the same reasons). 返回对局部变量的引用与返回对临时变量的引用是错误的(出于大致相同的原因)。 However, within the "no guarantees after an error" approach it will "work", meaning that it will fix the error message. 但是,在“错误后无保证”的方法内,它将“起作用”,这意味着它将修复错误消息。

The problem is that a non- const lvalue reference cannot bind to a temporary, which is an rvalue . 问题在于,非const左值引用不能绑定到临时值rvalue Only const lvalue references (in C++98 and C++11) or rvalue references (in C++11 only) can. 只有const左值引用(在C ++ 98和C ++ 11中)或右值引用(仅在C ++ 11中)可以。 This operator is trying to return an lvalue reference to a temporary created upon returning from the function: 该运算符试图返回对从函数返回时创建的临时对象的左值引用:

    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