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;
}