Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么常量限定符允许临时对象或右值?_C++_Reference_Rvalue Reference_Rvalue - Fatal编程技术网

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和临时函数的行为类似>RealOn><强>引用。因此,将它们绑定到非常量引用将违反这种性质。将引用声明为
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:是的,我明白了。要确保没有人试图更改右值的值,这就是常量的原因。如果链接到左值,则情况并非如此,因为它基本上是一个存储值的内存位置