以下代码是否合法(根据 C++11 和/或 C++14 标准)?
#include <iostream>
#include <utility>
using namespace std;
void foo(int &a) {
cout << a << endl;
}
int main() {
foo(reinterpret_cast<int &>(move(5)));
}
- 如果是,是否是未定义的行为?
- 如果这不是未定义的行为,我什至可以改变
a
吗?里面foo
没有成为 UB?
它在 clang 3.5 上编译,而不是在 gcc 4.9 上编译。 GCC 错误:
➤ g++-4.9 -std=c++1y sample.cpp -o sample
sample.cpp: In function 'int main()':
sample.cpp:11:40: error: invalid cast of an rvalue expression of type 'std::remove_reference<int>::type {aka int}' to type 'int&'
foo(reinterpret_cast<int &>(move(5)));
^
编辑
仅供引用,一个定制的类型转换比以前更简单,并且适用于 GCC 和 Clang 的 C++11,将是以下 lvalue
功能:
#include <iostream>
namespace non_std {
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }
}
void divs(int &a, int &b) {
int t = a;
a /= b;
b /= t;
}
int main() {
using namespace std;
using namespace non_std;
int i_care_for_this_one = 4;
divs(i_care_for_this_one, lvalue(2));
cout << i_care_for_this_one << endl;
}
最佳答案
更新:代码在 C++11 中格式错误。以下答案适用于 C++14。请参阅此答案末尾的注释。
我相信这段代码既格式良好又定义良好。原因如下。
std::move
的结果是一个 xvalue [1],它是一种 glvalue;并使用 reinterpret_cast
将左值转换为左值引用标准的措辞似乎是允许的:
A glvalue expression of type
T1
can be cast to the type “reference toT2
” if an expression of type “pointer toT1
” can be explicitly converted to the type “pointer toT2
” using areinterpret_cast
. The result refers to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference castreinterpret_cast<T&>(x)
has the same effect as the conversion*reinterpret_cast<T*>(&x)
with the built-in&
and*
operators (and similarly forreinterpret_cast<T&&>(x)
). — end note ] No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.73
因为“指向int
的指针”可以转换为“指向int
的指针”,所以这个reinterpret_cast
也是允许的。该标准没有说明目标类型必须是左值引用还是右值引用。
转换的结果由上面的段落明确定义:它指的是与源泛左值相同的对象——即一个临时的int
。值为 5
的对象. ([dcl.init.ref] 指定当纯右值绑定(bind)到引用时创建一个临时文件。)
通过 int&
访问值也不违反任何别名规则,因为原始对象的类型也是 int
.事实上,我相信通过由此获得的左值修改临时值甚至是明确定义的。
注意:C++11 的措辞是“左值表达式”,而不是“左值表达式”。带有“glvalue expression”的措辞来自 N3936,这是 C++14 的最终工作草案。我不是标准化过程如何运作的专家,但我相信这意味着委员会已经投票通过了将“左值”更改为“左值”,并且当 ISO 发布 C++14 标准时,它将会与上面所说的非常相似。
[1] 参数是函数的极少数情况除外;在这种情况下,结果是一个左值,因为没有函数右值。
关于c++ - reinterpret_cast(或任何强制转换)可以将 xvalues 转换为 lvalues 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26793072/