- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
TL;DR
给定以下代码:
int* ptr;
*ptr = 0;
*ptr
是否需要在应用间接之前对 ptr
进行 左值到右值 转换?
该标准在很多地方都涵盖了 lvalue-to-rvalue 的主题,但似乎没有指定足够的信息来确定 * 运算符 是否需要这样的转换。
详情
左值到右值的转换在 N3485 中有介绍。在 4.1
Lvalue-to-rvalue conversion 段落 1 中并说(强调我的前进):
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.[...]
*ptr = 0;
需要这种转换吗?
如果我们转到第 4
段 1 部分,它会说:
[...]A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.
那么什么时候需要?如果我们查看 5
Expressions 部分,9 部分提到了 lvalue-to-rvalue 转换,它说:
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. [...]
和第11段说:
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 [...]
这两个段落似乎都不适用于此代码示例和 5.3.1
一元运算符 段落 1 它说:
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 ]
它似乎不需要指针的 值,而且我没有看到任何指针转换的要求,我错过了什么吗?
我们为什么要关心?
我在其他问题中看到了一个答案和评论,声称使用未初始化的指针是未定义的行为,因为需要 lvalue-to-rvalue 转换 ptr
在应用间接之前。例如:Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior?提出了这个论点,我无法将该论点与该标准的任何最新草案版本中的内容相一致。由于我已经多次看到这一点,我想得到澄清。
未定义行为的实际证明并不重要,因为正如我在上面的链接问题中指出的那样,我们还有其他方法可以解决未定义行为。
最佳答案
我认为你是从一个相当倾斜的角度来处理这个问题,可以这么说。根据§5.3.1/1:
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.”
虽然这里没有讨论左值到右值的转换,但它要求表达式是指向对象或函数的指针。一个未初始化的指针不会(除非,可能是偶然的)是任何这样的东西,所以取消引用的尝试会产生未定义的行为。
关于c++ - 应用间接时,标准是否要求指针变量的左值到右值转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21053273/
我是 C++ 的新手,正在尝试编写如下接口(interface): template class Comparable { protected: Comparable(){};
什么是左值? 最佳答案 左值是可以分配给以下值的值: lvalue = rvalue; 它是“left value”或“lefthand value”的缩写,它基本上只是=符号左侧的值,即您为其分配值
这个问题已经有答案了: Why do C and C++ support memberwise assignment of arrays within structs, but not general
C++03 $14.1/6 - "A non-type non-reference template-parameter is not an lvalue." C++0x $14.2/6- "A no
这只是出于好奇我问... 我在任何地方看到的 99% 的代码,当使用“IF”时,将采用“If (RValue == LValue) ...”格式。例子: If (variableABC == "Hel
在 C++03 中,表达式可以是右值,也可以是左值。 在 C++11 中,表达式可以是: 右值 左值 x值 gl值 右值 两个类别变成了五个类别。 这些新的表达类别是什么? 这些新类别与现有的右值和左
我正在尝试将 div 向左移动指定数量的像素,我正在使用从此处获得的 slider : http://carpe.ambiprospect.com/slider/archive/v1.3/ 所以从示例
所以我有一个函数需要将 std::vector 作为参数。我想知道声明参数的最佳方式,这样底层数组就不会被深度复制,因为它可能相当大。 // which should I choose? void m
在 C++03 中,表达式要么是右值,要么是左值。 在 C++11 中,表达式可以是: 右值 左值 xvalue glvalue 右值 两类变成了五类。 这些新的表达类别是什么? 这些新类别与现有的右
我正在尝试实现类似 find 的方法来从容器中提取对值的引用,如果找不到该值或该值的类型不兼容,则返回一个默认值。 template const T& get (key_type k, const T
我有以下代码: #include using namespace std; void test(int& a) { cout << "lvalue." << endl; } void tes
我的搜索发现许多关于右值绑定(bind)到左值的帖子,但没有任何类似的帖子。对不起,如果它是重复的。 struct StrHolder { StrHolder(std::string&& s)
这是一个后续问题 C++0x rvalue references and temporaries 在上一个问题中,我问过这段代码应该如何工作: void f(const std::string &);
为什么这不起作用: ostream& operator' lvalue to 'std::basic_ostream&&'| error: initializing argument 1 of '
偶尔,我被问到一个技巧问题:x++ 和 ++x 哪个不能在 c 中留值?很多人告诉我++x不能,因为++x的汇编代码不返回寄存器。我对此表示怀疑。所以我做了一些实验。 C 代码: #include
所以这个问题与我为实际问题选择的解决方案有关,为了尽可能提供完整的图片,这个问题是这样的:基本上我有一个带有很多模板参数的函数,我正在尝试暴露给 Python。与用宏做一些噩梦般的事情来消除我需要的所
指针很简单。有一些内存保存着一个地址。要获得(有意义的)值,取消引用返回地址指向的内存中包含的值。 引用以某种方式做一些类似的事情:它们持有指向一个临时对象的“链接”。但是当我分配或使用引用时会发生什
下面是一些示例代码: #include class Foo { public: explicit Foo(int x) : data(x) {}; Foo& operator++() {
背景 以下代码块出现在 Scott Meyers 的名著 "Effective C++" 中第 3 项: class TextBlock { public: ... const cha
我是一名优秀的程序员,十分优秀!