C++ 为什么常量限定符允许临时对象或右值?
这是一个简单的函数,它求两个整数的和。现在这里的参数是整数引用C++ 为什么常量限定符允许临时对象或右值?,c++,reference,rvalue-reference,rvalue,C++,Reference,Rvalue Reference,Rvalue,这是一个简单的函数,它求两个整数的和。现在这里的参数是整数引用 #include <iostream> #include <cstdlib> using namespace std; int sum (int &a, int &b) { return(a + b); } int main() int a = 23, b = 34; cout << sum(a, b) << endl; // this works
#include <iostream>
#include <cstdlib>
using namespace std;
int sum (int &a, int &b)
{
return(a + b);
}
int main()
int a = 23, b = 34;
cout << sum(a, b) << endl; // this works
cout<< sum(2, 5) <<endl; // as expected, this does not work; compilation fails
return(0);
}
那么常量限定符做了什么更改,现在甚至引用变量也可以绑定到右值呢?在sum(2,5)
2和5都是右值
右值不能像第一个sum
int&
中的引用那样绑定到非常量左值引用,您需要const T&
,因此以后的函数对这两个引用都有效。在sum(2,5)
2和5中都是右值
右值不能绑定到非常量左值引用,就像第一个
sum
int&
中的引用一样,您需要const T&
,因此以后的函数可以同时用于这两个引用。左值表示对象,右值表示值(松散地说)。将右值绑定到非constlvalue引用将允许您修改该值-这到底意味着什么?如果您在函数中写入了a=3
,您将试图修改值2
,使其成为3
。这在概念上是没有意义的。但是,const
lvalue引用不允许修改,只允许您观察一个值,这是有意义的
但是,在右值表达式后面通常有对象,修改这些对象(例如窃取其资源)可能很有用。这正是引入右值引用的原因。左值表示对象,右值表示值(松散地说)。将右值绑定到非constlvalue引用将允许您修改该值-这到底意味着什么?如果您在函数中写入了
a=3
,您将试图修改值2
,使其成为3
。这在概念上是没有意义的。但是,const
lvalue引用不允许修改,只允许您观察一个值,这是有意义的
但是,在右值表达式后面通常有对象,修改这些对象(例如窃取其资源)可能很有用。这正是引入右值引用的原因。右值和临时值的行为类似于只读引用。因此,将它们绑定到非常量引用将违反这种性质。将引用声明为
const
就是在填写只读合同
在您的特定情况下,整数23等称为数字,并且本质上是常量(具有固定值)。在C++中,修改常量是未定义的行为,所以您的数字只绑定到const引用。 rValand和临时函数的行为类似
const
就是在填写只读合同
#include <iostream>
#include <cstdlib>
using namespace std;
int sum (int &a, int &b)
{
return(a + b);
}
int main()
int a = 23, b = 34;
cout << sum(a, b) << endl; // this works
cout<< sum(2, 5) <<endl; // as expected, this does not work; compilation fails
return(0);
}
在您的特定情况下,整数23等称为数字,并且本质上是常量(具有固定值)。在C++中,修改常量是未定义的行为,所以您的数字只绑定到const引用。在C++ 11中,可以更改它,以使它始终工作,不管您通过它:< /p>
#include <iostream>
#include <cstdlib>
using namespace std;
int sum (int &a, int &b)
{
return(a + b);
}
int main()
int a = 23, b = 34;
cout << sum(a, b) << endl; // this works
cout<< sum(2, 5) <<endl; // as expected, this does not work; compilation fails
return(0);
}
int sum (int &&a, int &&b)
{
return(a + b);
}
它将为您提供对
2
和5
的非常量引用(即,您可以通过a
和b
修改和(2,5)
调用中的值)。这是安全的,不会产生任何奇怪的副作用,即使它是临时对象而不是原语(如string(“foo”)
),因为sum()
的参数没有名称。它们没有名称会使您无法以任何方式观察修改。在C++11中,您可以将其更改为以下内容,使其始终工作,而不管您传递了什么:
int sum (int &&a, int &&b)
{
return(a + b);
}
它将为您提供对
2
和5
的非常量引用(即,您可以通过a
和b
修改和(2,5)
调用中的值)。这是安全的,不会产生任何奇怪的副作用,即使它是临时对象而不是原语(如string(“foo”)
),因为sum()
的参数没有名称。他们没有名字会让你无法以任何方式观察修改。想象如下:void foo(int&a){a=7;}int main(){foo(5);}
。这意味着什么?@OliCharlesworth它的意思与intmain(){int\uuu tmp=5;foo(\uu tmp);}
完全相同。当然,这是不可操作的,但是作为顶级表达式,1+1
也是不可操作的,而且它仍然是不被禁止的。@user4815162342:您不会期望foo(a)代码>相当于int\uu tmp=a;foo(tmp)代码>。相反,它实际上相当于5=7代码> @在C++数字中的USSR1515162442是常数,所以至少它会像<代码> const int×tMP=5;<代码>@OliCharlesworth:是的,我明白了。要确保没有人试图更改右值的值,这就是常量的原因。如果链接到左值,则情况并非如此,因为它基本上是一个存储可以更改的值的内存位置。想象一下:void foo(int&a){a=7;}int main(){foo(5);}
。这意味着什么?@OliCharlesworth它的意思与intmain(){int\uuu tmp=5;foo(\uu tmp);}
完全相同。当然,这是不可操作的,但是作为顶级表达式,1+1
也是不可操作的,而且它仍然是不被禁止的。@user4815162342:您不会期望foo(a)代码>相当于int\uu tmp=a;foo(tmp)代码>。相反,它实际上相当于5=7代码> @在C++数字中的USSR1515162442是常数,所以至少它会像<代码> const int×tMP=5;<代码>@OliCharlesworth:是的,我明白了。要确保没有人试图更改右值的值,这就是常量的原因。如果链接到左值,则情况并非如此,因为它基本上是一个存储值的内存位置