C++ 为返回引用的函数赋值 #包括 使用名称空间std; int&fun() { 静态int x=10; 返回x; } int main() { fun()=30; cout

C++ 为返回引用的函数赋值 #包括 使用名称空间std; int&fun() { 静态int x=10; 返回x; } int main() { fun()=30; cout,c++,return-value,return-type,C++,Return Value,Return Type,说“函数返回某物”是一种松散而草率的语言。如果你知道如何使用它,作为一种速记也可以,但在这种情况下,你会感到困惑 更正确的思考方法是对函数调用表达式求值。这样做会得到一个值。值可以是右值,也可以是左值(模细节) 当T是一个对象类型,并且您对一个具有返回类型T的函数求值时,您会得到一个类型为T的值,它是一个右值。另一方面,如果函数具有返回类型T&,您会得到一个类型为T的值,它是一个左值(值是绑定到return语句中的引用的对象)。返回引用非常有用 例如,这就是std::map::operator[

说“函数返回某物”是一种松散而草率的语言。如果你知道如何使用它,作为一种速记也可以,但在这种情况下,你会感到困惑

更正确的思考方法是对函数调用表达式求值。这样做会得到一个值。值可以是右值,也可以是左值(模细节)


T
是一个对象类型,并且您对一个具有返回类型
T
的函数求值时,您会得到一个类型为
T
的值,它是一个右值。另一方面,如果函数具有返回类型
T&
,您会得到一个类型为
T
的值,它是一个左值(值是绑定到
return
语句中的引用的对象)。

返回引用非常有用

例如,这就是
std::map::operator[]
所做的。我希望您喜欢编写
my\u map[key]=new\u value;
的可能性

如果一个常规(非运算符)函数返回一个引用,那么分配给它就可以了,我看不出有什么理由禁止这样做


你可以通过返回常量X&或者如果你真的愿意,通过返回
X
来阻止赋值。

因为函数的结果是左值。引用是左值。基本上,从函数返回非常量引用的整个过程就是能够赋值给它(或对引用对象执行其他修改)。

L-value是一个定位值。它表示它有地址。引用显然有地址。如果按值从fun()返回,则可以获得所需的左值:

#include<iostream>
using namespace std;

int &fun()
{
  static int x = 10;
  return x;
}
int main()
{
   fun() = 30;
   cout << fun();
   return 0;
}
#包括
使用名称空间std;
int fun()
{
静态int x=10;
返回x;
}
int main()
{
fun()=30;

除了其他的答案,请考虑下面的代码:

#include<iostream>
using namespace std;

int fun()
{
  static int x = 10;
  return x;
}
int main()
{
   fun() = 30;
   cout << fun();
   return 0;
}
这是一件非常自然的事情,如果您希望编译器在这方面给您一个错误,我会非常惊讶

现在,当您编写
someobj=value;
时,幕后真正发生的事情是调用
someobj.operator=(value);
。而
operator=()
只是类的另一个成员函数,与someclass()的
memberfunctions无异

总而言之,它归结为:

SomeClass& func() { ... }

func().memberFunctionOfSomeClass(value);
当然,这过于简单了,这种表示法不适用于内置类型,如
int
(但使用了相同的机制)


希望这能帮助您更好地理解其他人已经解释过的关于左值的内容。

我最初也被类似的代码弄糊涂了。这是“为什么我要给函数调用赋值,为什么编译器对它感到满意?”我问自己。但当你看看“后面”发生了什么,这是有道理的


正如和其他人所指出的,左值是有地址的“内存位置”,我们可以给它们赋值。你可以找到关于左值和右值的更多内容

当我们查看函数时:

func() = value;
// equivalent to
func().operator =(value);
// equivalent to
func().memberFunctionOfSomeClass(value);
我将&移到了类型,因此更明显的是,我们返回了对int的引用。
我们看到我们有x,它是左值-它有地址,我们可以分配给它。它也是静态的,这使得它很特别-如果它不是静态的,那么它的生存期(范围)在离开函数时,变量的作用将以堆栈展开结束,然后引用可以指向宇宙中存在的任何黑洞。然而,由于x是静态的,即使在我们离开函数后(以及当我们再次回到函数时),它也会存在,并且我们可以在函数之外访问它

我们返回对int的引用,由于我们返回x,因此它是对x的引用。然后我们可以使用该引用在函数外部更改x。因此:

int& fun()
{
    static int x = 10;
    return x;
}
我们只调用函数。变量x(在fun函数的范围内)被创建,它的值被赋值为10。它的地址和值在函数离开后仍然存在,但我们不能使用它的值,因为我们没有它的地址

int main()
{
    fun();
我们调用函数,然后更改x的值。x值通过函数返回的引用进行更改。注意:函数首先调用,只有在函数调用完成后,才进行赋值

    fun() = 30;
现在我们(最后)保留对函数返回的x的引用。现在我们可以更改x,而无需首先调用函数。(reference\u to\u x可能与x在fun函数中的地址相同)

这一次我们创建了新的int,我们只是复制x的值(通过引用)。这个新int有自己的地址,它不指向x,就像引用x一样

    int copy_of_x = fun(); // no & this time
我们通过引用指定了x值5,我们甚至没有调用该函数。x的副本没有更改

    reference_to_x = 5;
我们将新的int值更改为15。x没有更改,因为x的副本有自己的地址

    copy_of_x = 15;

正如和其他人所指出的,我们使用类似的方法,通过容器和自定义重写大量返回引用

}
我们没有映射中“存储”的字符串的地址,因此我们调用map的这个重写函数,传递它的键,这样map就知道我们要访问哪个字符串,并且它返回对该字符串的引用,我们可以使用该字符串来更改值。注意:再次,该函数首先被调用,并且只有在它完成后才被调用(map找到了正确的字符串并返回了对它的引用)分配发生了。这就像fun()=10一样,只是更美好

希望如此
}
std::map<std::string, std::string> map = {};

map["hello"] = "Ahoj";
// is equal to
map.operator[]("hello") = "Ahoj"; // returns reference to std::string
// could be done also this way
std::string& reference_to_string_in_map = map.operator[]("hello");
reference_to_string_in_map = "Ahoj";
std::string& map::operator[]( const std::string& key ); // returns reference
#include<iostream> 
using namespace std; 

int *fun() //fun defined to return pointer to int
{ 
    static int x = 10; 
    return &x; // returning address of static int
} 
int main() 
{ 
    *fun() = 30; //execute fun(), take its return value and dereference it,
                 //yielding an lvalue, which you can assign to. 
    cout << *fun();  //you also need to dereference here
    return 0; 
}