返回非const左值引用

BRa*_*t27 1 c++ const

我正在尝试使用书籍学习计算机图形学交互式计算机图形 - 自上而下的方法,示例的代码就在这个链接中

有一个名为'mat.h'的头库提供了一些矩阵实用程序,但是当我尝试使用Xcode编译时,会抛出以下错误:

对类型'Angel :: mat2'的非const左值引用不能绑定到'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
Run Code Online (Sandbox Code Playgroud)

我只是评论它,因为它只是在调试应用程序时编译,但我想知道问题是什么以及如何解决它.

AnT*_*AnT 6

严格来说,虽然错误的正式原因是尝试将非const引用绑定到临时,但这里真正的问题是尝试返回引用,对临时对象的任何引用.引用是否为const无关紧要.

在return语句完成后,临时对象将被销毁,从而导致绑定到正在被返回的现在被破坏的对象的悬挂引用.换句话说,即使我们尝试通过将返回类型更改为const引用来"修复"此代码,它仍然无法正常工作.

而且,看起来设计这个函数应该返回一个非const引用,这意味着改变这个函数的返回类型不是一个选项.非const引用是复合赋值运算符通常返回的内容.调试分支应该提前终止(当然,在"除零"的情况下,返回一些东西,只是为了使代码编译).

实现这一点的一种方法是声明一个类型的独立对象mat2(例如,作为类的静态成员mat2)并返回对它的引用.即宣布

class mat2 {
  ...
#ifdef DEBUG
  static mat2 bad_result;
#endif // DEBUG
};
Run Code Online (Sandbox Code Playgroud)

定义它

#ifdef DEBUG
mat2 mat2::bad_result;
#endif // DEBUG
Run Code Online (Sandbox Code Playgroud)

然后呢

return bad_result;
Run Code Online (Sandbox Code Playgroud)

每当检测到错误时.

或者(更容易)您可以在该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
Run Code Online (Sandbox Code Playgroud)

当然,这种设计存在明显的缺陷,因为外部代码将能够修改返回的对象,这是不可取的.但是,最有可能的想法是,一旦打印出错误消息,程序的行为就不能得到保证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
Run Code Online (Sandbox Code Playgroud)

返回对局部变量的引用与返回对临时变量的引用一样错误(原因大致相同).但是,在"错误后无保证"方法中,它将"工作",这意味着它将修复错误消息.