提问人:UPinar 提问时间:3/11/2023 最后编辑:Vlad from MoscowUPinar 更新时间:3/11/2023 访问量:60
为什么函数参数(Myclass)可以有L和R值,但相同的返回类型(Myclass)只能返回R值?
Why a function parameter(Myclass) can have L and R values but same return type (Myclass) can only returns R value?
问:
我很难理解这个概念。 我可以发送 L 值和 R 值作为参数
Myclass foo(Myclass)
但不能从该函数返回 L 和 R 值。只有 R 值出来。
我想知道为什么会这样?
class Myclass {};
Myclass fooReturnsL(Myclass b)
{
Myclass a;
return a;
}
Myclass fooReturnsR(Myclass b)
{
return Myclass{};
}
int main()
{
Myclass var_Myclass;
Myclass& lref = fooReturnsL(var_Myclass); // sythax error
Myclass& lref = fooReturnsL(Myclass{}); // sythax error
Myclass&& rref = fooReturnsR(var_Myclass); // no error
Myclass&& rref = fooReturnsR(Myclass{}); // no error
}
有没有随时可以返回 L 值?Myclass fooReturnsL(Myclass b)
答:
1赞
Vlad from Moscow
3/11/2023
#1
此功能
Myclass fooReturnsL(Myclass b)
{
Myclass a;
return a;
}
返回具有自动存储持续时间的对象,该对象在退出函数后将不处于活动状态。
因此,您不能返回不存在的对象的引用。
例如,您可以声明该函数
Myclass & fooReturnsL(Myclass &b)
{
//... some other code
return b;
}
并称它为
Myclass var_Myclass;
Myclass& lref = fooReturnsL(var_Myclass);
如果尝试从函数返回对具有自动存储持续时间的本地对象的引用,则程序行为将未定义。
考虑以下演示程序(前提是它将被编译)
#include <iostream>
class Myclass
{
public:
~Myclass()
{
std::cout << "Myclass::~Myclass() called\n" ;
}
};
Myclass & fooReturnsL()
{
Myclass a;
return a;
}
int main()
{
Myclass &t = fooReturnsL();
std::cout << "Press any key to continue...";
}
程序输出为
Myclass::~Myclass() called
Press any key to continue...
如您所见,函数中声明的对象已销毁。所以引用是一个悬空的引用。
评论
0赞
UPinar
3/11/2023
当我在函数中创建一个对象时,有一个自动存储持续时间,并且在函数执行后它不会处于活动状态,但我也可以与 main() 中的 L 值引用绑定,例如Myclass obj;
Myclass& foo(Myclass a)
return obj
obj
Myclass& lref = foo(var_Myclass)
1赞
Vlad from Moscow
3/11/2023
@UPinar 此类代码具有未定义的行为。
0赞
UPinar
3/11/2023
还有 1 个问题,当发送 var_Myclass 或 Myclass{} 作为参数复制 ctor 时调用对吗?if 函数如下所示Myclass& foo(Myclass)
0赞
Vlad from Moscow
3/11/2023
@UPinar 对于用作参数表达式的临时对象,可以省略复制构造函数。它被称为复制构造函数省略。
0赞
UPinar
3/11/2023
哦,很酷,所以直接在 foo() 函数堆栈中创建的 Myclass 对象,就像一个临时对象
评论
fooReturnsL(var_Myclass)
并且是纯右值 (en.cppreference.com/w/cpp/language/value_category)。因此,它们不能绑定到左值引用,因为这将允许更改临时引用。fooReturnsL(Myclass{})