C++ 类、右值和右值引用

C++ 类、右值和右值引用,c++,reference,rvalue-reference,rvalue,lvalue,C++,Reference,Rvalue Reference,Rvalue,Lvalue,左值是一个绑定到内存的确定区域的值,而右值是一个表达式值,它的存在是暂时的,不一定指内存的确定区域。每当在预期右值的位置使用左值时,编译器将执行左值到右值的转换,然后继续求值 无论何时构造临时(匿名)类对象或从函数返回临时类对象,尽管该对象是临时的,但它是可寻址的。但是,该对象仍然是有效的右值。这意味着对象是a)一个可寻址的右值,或者b)当编译器期望使用左值时,正在从左值隐式转换为右值 例如: class A { public: int x; A(int a) { x = a;

左值是一个绑定到内存的确定区域的值,而右值是一个表达式值,它的存在是暂时的,不一定指内存的确定区域。每当在预期右值的位置使用左值时,编译器将执行左值到右值的转换,然后继续求值

无论何时构造临时(匿名)类对象或从函数返回临时类对象,尽管该对象是临时的,但它是可寻址的。但是,该对象仍然是有效的右值。这意味着对象是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
}
产生以下输出:

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月)发生了变化。下面将对此进行详细介绍

当函数完成执行时, 然后它构造一个临时
a
使用
a
作为其参数的 调用
A::A(A&)

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

当删除一个 满足或将满足复制操作 除了源代码 对象是函数参数,并且 要复制的对象已指定 通过左值,重载解析为 选择要创建的副本的构造函数 首先执行,就好像对象是 由右值指定。如果过载 解析失败,或者 选定对象的第一个参数 构造函数不是右值引用 到对象的类型(可能是 cv合格),过载分辨率为 再次执行,考虑到 对象作为左值。[注:此 必须使用两级过载解决方案 无论是否复制,都将执行 将发生省略。它决定了 如果省略为,则调用构造函数 未执行,并且已选择 构造函数必须是可访问的,即使 电话被省略了。-结束语]

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

一个给定的对象如何与两个对象匹配 右值引用和左值 推荐人

在提及该声明时:

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


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

“左值”和“右值”指的是表达式,而不是对象。谢谢。我猜接下来的问题是a对象如何同时绑定到右值和左值引用?另外:“int n=3;n是一个引用int对象的表达式。表达式n是一个左值。”如果这是正确的,那么
a
对象(上面)在初始化时不会被认为是一个表达式吗?@Howard感谢大家的理解。但是没有,在我最初的问题中没有o型。调用了
A::A(A&)
。您使用的是哪种编译器?我使用的是MSVC++除了源对象是一个函数参数这一事实之外,还有什么是“或者将要满足的”意思?@没有人:看起来[class.copy]/p33只是还没有在编译器中实现。这一部分我有点惊讶
return a;