C++ 为什么我会犯这个错误;类型为';的非常量引用的初始化无效;A&';从类型为';A'&引用;

C++ 为什么我会犯这个错误;类型为';的非常量引用的初始化无效;A&';从类型为';A'&引用;,c++,c++11,reference,C++,C++11,Reference,给定以下代码: #include <iostream> using std::ostream; class A { int x; public: A(int x) : x(x) { } A& operator+=(const A& a) { this->x = this->x + a.x; return *this; } friend ostream&

给定以下代码:

#include <iostream>
using std::ostream;

class A {
    int x;
public:
    A(int x) :
            x(x) {
    }
    A& operator+=(const A& a) {
        this->x = this->x + a.x;
        return *this;
    }
    friend ostream& operator<<(ostream& os, const A& a);

};

A operator+(const A& a1, const A& a2) {
    return A(a1) + a2;
}

ostream& operator<<(ostream& os, const A& a) {
    return os << a.x;
}

int main() {
    const A a1(2);
    A& sum = a1 + a1; // error**************
    std::cout << sum;
}
#包括
使用std::ostream;
甲级{
int x;
公众:
A(int x):
x(x){
}
运算符+=(常量A&A){
这个->x=这个->x+a.x;
归还*这个;
}
friend ostream&operator引用不能绑定到匿名临时文件。
a1+a1
是匿名临时文件

出于兴趣,
const
引用可以绑定,因此允许
const a&sum=a1+a1;
。此外,在这种特殊情况下,该临时变量的生存期会延长到引用的生存期(尽管需要注意的是,这不是可传递的).

引用不能绑定到匿名临时文件。
a1+a1
是匿名临时文件

出于兴趣,
const
引用可以绑定,因此允许
const a&sum=a1+a1;
。此外,在这种特殊情况下,该临时变量的生存期会延长到引用的生存期(尽管需要注意的是,这不是可传递的)

这将返回类型为
a
的新对象(匿名临时对象)

A& sum = a1 + a1;
您尝试将此临时绑定到(非const)引用;因此尝试对生命周期即将结束的对象进行引用。希望这在C++中是不合法的。您确实需要“在该对象中存储”:

A sum = a1 + a1;

特殊情况:

A const& sum = a1 + a1;
当临时对象绑定到常量引用时,此对象的生存期将延长到引用的生存期。这对函数参数很有用,但此处不建议这样做

这将返回类型为
a
的新对象(匿名临时对象)

A& sum = a1 + a1;
您尝试将此临时绑定到(非const)引用;因此尝试对生命周期即将结束的对象进行引用。希望这在C++中是不合法的。您确实需要“在该对象中存储”:

A sum = a1 + a1;

特殊情况:

A const& sum = a1 + a1;

当临时对象绑定到常量引用时,此对象的生存期将延长到引用的生存期。这对函数参数很有用,但在此处不建议使用。

答案在错误消息中:非常量引用的初始化无效。使用常量引用:
const a&sum=a1+a1;
a1+a1
生成临时的。临时的不能绑定到非常量引用。@S.M.Hye,你能解释一下使用非常量引用有什么问题吗?为什么我必须使用常量引用?很简单:因为你不能修改临时对象(右值)。如果尝试将其分配给非常量引用,则会告诉编译器以后要修改临时对象。答案在错误消息中:非常量引用的初始化无效。使用常量引用:
const a&sum=a1+a1;
a1+a1
生成临时对象。临时对象无法绑定到非常量引用@S.M.Hye,你能解释一下使用非常量引用有什么问题吗?为什么我必须使用常量引用?简而言之:因为你不能修改临时对象(右值)。如果你试图将其分配给非常量引用,你会告诉编译器你以后要修改临时对象。事实上,什么是“fresh object/anonymous temporary”?换句话说,为什么不考虑我问题中的情况-以下代码有效?:
A a1(2);A&s=a1;
@Software\u t因为您命名了
a1
。它存在于一个范围内,并且有一个定义的生命周期。好的,我知道理解这个概念,因为在我的问题中它是右值,所以它是有问题的,不是吗?右值是---简化---一个临时的。事实上,什么是定义为“新对象/匿名临时的”“?换句话说,尽管我的问题中的情况如此,为什么?以下代码是有效的:
a1(2);A&s=a1;
@Software\u t是因为您命名了
a1
。它存在于一个范围内,并且有一个定义的生命周期。好吧,我知道理解这个概念,因为在我的问题中它是右值,所以它是有问题的,不是吗?右值是---简化---一个临时值。值得一提的是,MSVC14实际上允许将临时值绑定到非常量引用作为扩展(可能包括生存期扩展)。您不应该这样做,但可能有人会惊讶于Visual Studio对此表示满意。值得一提的是,MSVC14实际上允许将临时引用绑定到非常量引用作为扩展(可能包括生存期扩展).不是说你应该这么做,但也许有人会惊讶于Visual Studio对它的认可。