gpt4 book ai didi

c++ - 类、右值和右值引用

转载 作者:IT老高 更新时间:2023-10-28 23:01:59 26 4
gpt4 key购买 nike

左值是绑定(bind)到内存的确定区域的值,而右值是一个表达式值,其存在是暂时的,不一定指向内存的确定区域。每当在需要右值的位置使用左值时,编译器都会执行左值到右值的转换,然后继续求值。

http://www.eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues

每当我们构造一个临时(匿名)类对象或从函数返回一个临时类对象时,虽然该对象是临时的,但它是可寻址的。但是,该对象仍然是有效的右值。这意味着该对象是 a) 可寻址的右值或 b) 当编译器期望使用左值时,它正在从左值隐式转换为右值。

例如:

class A
{
public:
int x;
A(int a) { x = a; std::cout << "int conversion ctor\n"; }
A(A&) { std::cout << "lvalue copy ctor\n"; }
A(A&&) { std::cout << "rvalue copy ctor\n"; }
};
A ret_a(A a)
{
return a;
}

int main(void)
{
&A(5); // A(5) is an addressable object
A&& rvalue = A(5); // A(5) is also an rvalue
}

我们还知道函数返回(在以下情况下为a)的临时对象是左值,如这段代码:

int main(void)
{
ret_a(A(5));
}

产生以下输出:

int 转换函数

左值复制ctor

表示使用实参A(5)调用函数ret_a调用转换构造函数A::A(int)它用值 5 构造函数的形式参数 a

当函数完成执行后,它会构造一个临时的A对象,使用a作为参数,调用A::A(A&)。但是,如果我们要从重载构造函数列表中删除 A::A(A&),返回的临时对象仍然会匹配右值引用构造函数 A::A(A&&) .

这是我不太理解的:对象 a 如何同时匹配右值引用和左值引用?很明显 A::A(A&)A::A(A&&) 更好的匹配(因此 a 必须是一个左值)。但是,由于不能将右值引用初始化为左值,鉴于形式参数 a 是左值,它应该无法匹配对 A::A(A&&) 的调用。如果编译器正在进行左值到右值的转换,那将是微不足道的。事实上,从 'A' 到 'A&' 的转换也是微不足道的,两个函数应该具有相同的隐式转换序列等级,因此,当两个 A::A(A&)A::A(A&&) 在重载函数候选集中。

此外,问题(我之前问过的)是:

给定对象如何同时匹配右值引用和左值引用?

最佳答案

对我来说:

int main(void)
{
ret_a(A(5));
}

产量:

int conversion ctor
rvalue copy ctor

(即右值,而不是左值)。这是您的编译器中的一个错误。然而,这是可以理解的,因为这种行为的规则仅在几个月前(2010 年 11 月)发生了变化。更多内容请参见下文。

When the function completes execution, it then constructs a temporary A object using a as its argument, which invokes A::A(A&).

其实没有。当函数 ret_a 完成执行时,它会使用 a 作为参数构造一个临时的 A 对象,该对象调用 A:A( A&&)。这是由于 [class.copy]/p33] 1 :

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. — end note ]

但是,如果您删除 A::A(A&&) 构造函数,则将选择 A::A(&) 作为返回值。尽管在这种情况下,参数 a 的构造将失败,因为您无法使用右值构造它。但是暂时忽略这一点,我相信您的最终问题是:

How can a given object match both an rvalue reference and an lvalue reference?

在引用语句中:

return a;

答案在上面引用的标准草案段落中:尝试第一次重载解析,就好像 a 是一个右值一样。如果失败,则使用 a 作为左值再次尝试重载解析。这种两阶段过程仅在允许复制省略的上下文中尝试(例如返回语句)。

C++0x 草案最近已更改为在返回按值传递的参数时允许两阶段重载解析过程(如您的示例中所示)。这就是我们看到的不同编译器行为不同的原因。

关于c++ - 类、右值和右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5266783/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com