【发布时间】:2014-01-17 23:42:21
【问题描述】:
我看到在整个 C++ 标准的许多地方都使用了术语“左值到右值转换”。据我所知,这种转换通常是隐式完成的。
标准措辞的一个出乎意料的(对我而言)特征是他们决定将左值到右值视为一种转换。如果他们说glvalue总是可以接受而不是prvalue怎么办。这句话真的会有不同的含义吗?例如,我们读到 lvalues 和 xvalues 是 glvalues 的例子。我们没有读到左值和 xvalue 可以转换为 glvalues。意思有区别吗?
在我第一次遇到这个术语之前,我曾经在心理上或多或少地对左值和右值进行建模,如下所示:“左值总是能够充当右值,但另外还可以出现在左侧= 的一侧,&" 的右侧。
对我来说,这是一种直观的行为,如果我有一个变量名,那么我可以把这个名字放在任何我应该放置文字的地方。这个模型似乎与标准中使用的左值到右值隐式转换术语一致,只要保证这种隐式转换会发生。
但是,因为他们使用这个术语,我开始怀疑隐式左值到右值的转换是否在某些情况下会失败。也就是说,也许我的心智模型在这里是错误的。这是标准的相关部分:(感谢评论者)。
当一个泛右值出现在一个期望纯右值的上下文中时,这个泛左值就被转换成一个纯右值;见 4.1、4.2 和 4.3。 [注意:将右值引用绑定到左值的尝试不是这样的上下文;见 8.5.3 .—尾注]
我了解他们在注释中的描述如下:
int x = 1;
int && y = x; //in this declaration context, x won't bind to y.
// but the literal 1 would have bound, so this is one context where the implicit
// lvalue to rvalue conversion did not happen.
// The expression on right is an lvalue. if it had been a prvalue, it would have bound.
// Therefore, the lvalue to prvalue conversion did not happen (which is good).
所以,我的问题是(是):
1) 有人可以澄清这种转换可以隐式发生的上下文吗?具体来说,除了绑定到右值引用的上下文之外,是否还有其他无法隐式发生左值到右值转换的地方?
2) 此外,从句中的括号[Note:...] 使我们似乎可以从之前的句子中找出它。那是标准的哪一部分?
3) 这是否意味着右值引用绑定不是我们期望纯右值表达式(在右侧)的上下文?
4) 与其他转换一样,glvalue 到prvalue 的转换是否涉及运行时的工作,可以让我观察到它?
我在这里的目的不是问是否需要允许这样的转换。我正在尝试学习以标准为起点向自己解释这段代码的行为。
一个好的答案是通过我上面引用的引用并解释(基于解析文本)其中的注释是否也隐含在其文本中。然后它可能会添加任何其他引号,让我知道这种转换可能无法隐式发生的其他上下文,或者解释没有更多这样的上下文。也许一般讨论为什么将 glvalue 到 prvalue 视为转换。
【问题讨论】:
-
请注意,
int && y = x;本身不是一个表达式,而是一个声明。因此,左值到右值的转换不会自动应用于“=右侧的操作数”。 -
这不是左值到右值的转换失败;那是右值引用绑定失败。
-
另请注意,左值仍然可以“充当”(可以转换为)右值,即使对于右值引用绑定也是如此。您只需手动应用左值到右值的转换;正如我所说,它不会自动应用于引用绑定:
int x = 42; int && y = +x;(一元+调用左值到右值转换)——但这不会将y绑定到x,而是绑定到临时的,就像int && y = 42;一样。 -
@DyP:好吧,右边还有一个表达式......但我认为标准实际上是说,“当需要一个右值时;绑定到引用是不是 这种情况”。
-
@orm 需要一个 xvalue。当您使用 prvalue 初始化 rvalue 引用时,它实际上绑定到使用该 prvalue 初始化的临时 xvalue。换句话说,
int && x = 1; ++x;实际上并没有改变1的值。但是int y = 42; int &&x = std::move(y); ++x;会改变y的值。
标签: c++ c++11 implicit-conversion lvalue-to-rvalue