问题标签 [lvalue-to-rvalue]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
18095 浏览

c++ - 左值到右值的隐式转换

我看到在整个 C++ 标准的许多地方都使用了术语“左值到右值转换”。据我所知,这种转换通常是隐式完成的。

标准措辞的一个出乎意料的(对我而言)特征是他们决定将左值到右值视为一种转换。如果他们说glvalue总是可以接受而不是prvalue怎么办。这句话真的会有不同的含义吗?例如,我们读到 lvalues 和 xvalues 是 glvalues 的例子。我们没有读到左值和 xvalue 可以转换为 glvalues。意思有区别吗?

在我第一次遇到这个术语之前,我曾经在心理上或多或少地对左值和右值进行建模,如下所示:“左值总是能够充当右值,但此外还可以出现在 an 的左侧和 an=的右侧&”。

对我来说,这是一种直观的行为,如果我有一个变量名,那么我可以把这个名字放在我应该放文字的任何地方。这个模型似乎与标准中使用的左值到右值隐式转换术语一致,只要保证这种隐式转换发生。

但是,因为他们使用这个术语,我开始怀疑隐式左值到右值的转换在某些情况下是否会失败。也就是说,也许我的心智模型在这里是错误的。这是标准的相关部分:(感谢评论者)。

每当一个泛右值出现在预期纯右值的上下文中时,该泛左值就被转换为一个纯右值;见 4.1、4.2 和 4.3。[注意:将右值引用绑定到左值的尝试不是这样的上下文;见 8.5.3 .—尾注]

我了解他们在注释中描述的内容如下:

所以,我的问题是(是):

1)有人可以澄清这种转换可以隐式发生的上下文吗?具体来说,除了绑定到右值引用的上下文之外,是否还有其他无法隐式发生左值到右值转换的地方?

2)此外,[Note:...]从句中的括号使我们似乎可以从之前的句子中弄清楚。那是标准的哪一部分?

3)这是否意味着右值引用绑定不是我们期望纯右值表达式(在右侧)的上下文?

4) 与其他转换一样,glvalue 到prvalue 的转换是否涉及运行时的工作,可以让我观察到它?

我在这里的目的不是问是否需要允许这样的转换。我正在尝试学习以标准为起点向自己解释这段代码的行为。

一个好的答案是通过我上面的引用并解释(基于解析文本)其中的注释是否也隐含在其文本中。然后它可能会添加任何其他引号,让我知道这种转换可能无法隐式发生的其他上下文,或者解释没有更多这样的上下文。也许一般讨论为什么将 glvalue 到 prvalue 视为转换。

0 投票
2 回答
922 浏览

c++ - Does the standard mandate an lvalue-to-rvalue conversion of the pointer variable when applying indirection?

TL;DR

Given the following code:

does *ptr require an lvalue-to-rvalue conversion of ptr before applying indirection?

The standard covers the topic of lvalue-to-rvalue in many places but does not seem to specify enough information to determine whether the * operator require such a conversion.

Details

The lvalue-to-rvalue conversion is covered in N3485 in section 4.1 Lvalue-to-rvalue conversion paragraph 1 and says (emphasis mine going forward):

A glvalue (3.10) of a non-function, non-array type T can be converted to a prvalue.53 If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior.[...]

So does *ptr = 0; necessitate this conversion?

If we go to section 4 paragraph 1 it says:

[...]A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.

So when is it necessary? If we look at section 5 Expressions the lvalue-to-rvalue conversion is mentioned in paragraph 9 which says:

Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are applied to convert the expression to a prvalue. [...]

and paragraph 11 which says:

In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression.[...] The lvalue-to-rvalue conversion (4.1) is applied if and only if the expression is an lvalue of volatile-qualified type and it is one of the following [...]

neither paragraph seems to apply to this code sample and 5.3.1 Unary operators paragraph 1 it says:

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.” [ Note: indirection through a pointer to an incomplete type (other than cv void) is valid. The lvalue thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to a prvalue, see 4.1. —end note ]

it does not seem to require the value of the pointer and I don't see any requirements for a conversion of the pointer here am I missing something?

Why do we care?

I have seen an answer and comments in other questions that claim the use of an uninitialized pointer is undefined behavior due the need for an lvalue-to-rvalue conversion of ptr before applying indirection. For example: Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior? makes this argument and I can not reconcile the argument with what is laid out in any of the recent draft versions of the standard. Since I have seen this several times I wanted to get clarification.

The actual proof of undefined behavior is not as important since as I noted in the linked question above we have others way to get to undefined behavior.

0 投票
2 回答
691 浏览

c++ - 带有两个运算符的 C++11 模棱两可的错误(一个左值第二个右值)

更新在底部。

我想让 void tree::operator = ( tree t ) 使用右值。(在这种情况下,一般来说,由于效率,我想以不同的方式处理它们)

我已经对其进行了编码,使用 std::move 来确保它将使用右值,但编译器说它不知道选择哪个运算符。他不应该使用右值选择那个吗?

代码:

编译器错误:

我正在使用 clang-503.0.38。(但使用 gcc 4.8 是同样的错误)

更新

好的,现在我有:

它正在工作。明天我将发布我从中学到的东西作为答案。

0 投票
2 回答
1018 浏览

c++ - swap() 会导致未定义的行为吗?

我试图std::swap从 [C++11:utility.swap] 中了解条件。模板定义为

(加上一些noexcept细节)并具有“交换存储在两个位置的值”的效果。

以下程序是否已明确定义?

如果我自己编写交换代码(即int tmp = m; m = n; n = tmp;),它将具有未定义的行为,因为它会尝试对未初始化的对象进行左值到右值的转换。但是标准std::swap函数似乎并没有附加任何条件,也不能从规范中得出存在任何左值到右值和因此 UB 的规范。

标准是否需要std::swap对未初始化的对象执行一些明确定义的魔法?

为了澄清这一点,请考虑函数void f(int & n) { n = 25; },它永远不会有未定义的行为(因为它不从 读取n)。

0 投票
3 回答
35948 浏览

c++ - 类型的非常量引用的无效初始化

在以下代码中,我无法将临时对象作为参数传递给printAge函数:

我得到的错误是:

我意识到这与将 lValue 传递给期望 rValue 的函数有关...有没有办法通过使用 std::move 或其他方法将我的 lValue 转换为 rValue?我尝试采用常量参数,但这似乎不起作用。

0 投票
1 回答
844 浏览

c++ - 了解左值到右值转换的示例

我很难理解这段代码(来自 C++14 草案标准[conv.lval]的示例)如何为g(false). 为什么constexpr使程序有效?

另外,“不访问y.n”是什么意思?在对我们的两次调用中,g()我们都返回了n数据成员,那么为什么最后一行说它不访问它呢?

0 投票
2 回答
108 浏览

c++ - 右值引用如何在这里工作?

我对以下代码感到困惑:

它的输出是1。我不明白这是如何工作的。static_cast应该将左值转换x为 xvalue,然后将其分配给rvx. 为什么递增rvx会导致变化x?这是因为转换后的左值到右值本质上位于相同的内存位置,但现在它只是被认为是右值?我的印象是(这可能是错误的)演员不知何故从它的论点中创造了一个临时的。

0 投票
0 回答
70 浏览

c++ - std::move 如何与采用非常量引用的复制构造函数一起工作?

我正在阅读有关 std::move 的信息。根据很少的材料,我得出结论 std::move 只是一个将其参数类型转换为右值引用的函数。

我还读到,右值引用可以与将其参数作为常量引用的函数一起使用。这是有意义的,因为对象的内容保证不会改变。

为了验证这些想法,我用下面的一个类做了一个非常简单的实验。

我创建了一个对象t1并使用std::move将其转换为右值引用,并尝试通过调用复制构造函数创建另一个对象t2 。

神秘的部分是,即使我不提供移动构造函数,它也可以与我故意将其参数定义为非常量引用的复制构造函数一起使用。

但是,如果 std::move 将t1的类型转换为右值引用,编译器如何将其绑定到左值引用?

顺便说一句,我正在使用“Microsoft (R) Microsoft Visual Studio 2012 版本 11.0.50727.1”。

你能解释一下我在这里缺少什么吗?

非常感谢。

0 投票
1 回答
692 浏览

c - 从C中的二叉搜索树中删除一个节点

我正在尝试从二叉搜索树中删除一个节点。但是当我想测试该功能时,我会在“案例 3:两个孩子”中收到一条错误消息。

此行会导致错误消息。它说:左操作数必须是左值。我是 C 和二叉搜索树的新手。我无法弄清楚,为什么这条线不起作用。我在互联网上找到了很多关于如何实现删除功能的想法。所有这些方法都使用这行代码。

以下是完整的功能。

(greaterThan、lessThan、toLowerCase 是我实现的辅助功能。它们肯定工作正常)

如果有人能告诉我为什么这条线不起作用,那就太好了。以及如何解决此错误。

谢谢你!

0 投票
2 回答
995 浏览

c++ - 左侧的右值

为什么要编译这段代码?我认为 ctor 返回的右值不在内存中,因此不能用作左值。