问题描述
以下代码是否合法(通过C ++ 11和/或C ++ 14标准)?
Is the following code legal (by C++11 and/or C++14 standard(s))?
#include <iostream>
#include <utility>
using namespace std;
void foo(int &a) {
cout << a << endl;
}
int main() {
foo(reinterpret_cast<int &>(move(5)));
}
- 如果是,是否未定义行为? / li>
- 如果不是未定义的行为,我甚至可以在
内它变成UB?
它在clang 3.5上编译,而不是在gcc 4.9上编译。
GCC错误:
It compiles on clang 3.5, not on gcc 4.9.GCC error:
➤ 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)));
^
EDIT
FYI,一个定制的铸造,比以前更少毛,它工作在C ++ 11为GCC和Clang,将是以下 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;
}
推荐答案
/ strong>代码在C ++ 11中是不成形的。下面的答案是为C ++ 14。
Update: The code is ill-formed in C++11. Answer below is for C++14. See note at the end of this answer.
我相信此代码格式正确和定义良好。这是为什么。
I believe this code is both well-formed and well-defined. Here's why.
std :: move
的结果是xvalue [1] ;并将标量转换为一个左值引用 reinterpret_cast
似乎被标准的措辞允许:
The result of std::move
is an xvalue [1], which is a type of glvalue; and converting a glvalue to an lvalue reference with reinterpret_cast
appears to be allowed by the wording of the standard:
由于 int
的指针可以转换为指向 int
reinterpret_cast
也是允许的。该标准没有说明目标类型是否是一个左值引用或右值引用。
Since "pointer to int
" can be converted to "pointer to int
", this reinterpret_cast
is also allowed. The standard doesn't say anything about whether the destination type has to be an lvalue reference or rvalue reference.
转换的结果是由上述段落:它引用与源glvalue相同的对象 - 即,值为 5的临时
。 ([dcl.init.ref]指定当一个prvalue绑定到一个引用时创建一个临时变量。) int
对象
The result of the cast is well-defined by the paragraph above: it refers to the same object as the source glvalue---that is, a temporary int
object with the value 5
. ([dcl.init.ref] specifies that a temporary is created when a prvalue is bound to a reference.)
通过 int&
也不违反任何别名规则,因为原始对象也是 int
类型。事实上,我相信,通过这样获得的左值来修改临时值也是很明确的。
Accessing the value through the int&
also doesn't violate any aliasing rules since the original object was also of type int
. In fact I believe it would even be well-defined to modify the temporary through the lvalue thus obtained.
注意:措辞表示左值表达式,而不是glvalue表达式。与glvalue expression的措辞是从N3936,这是C ++ 14的最后工作草案。我不是标准化过程如何工作的专家,但我相信这意味着左值到glvalue的变化已经被委员会投票,当ISO发布C ++ 14标准时,它会非常类似于上面所说的。
Note: The C++11 wording says "lvalue expression", not "glvalue expression". The wording with "glvalue expression" is from N3936, which is the final working draft for C++14. I'm not an expert in how the standardization process works, but I believe this means that the change of "lvalue" to "glvalue" was already voted in by the committee, and when ISO publishes the C++14 standard, it's going to be pretty similar to what it says above.
[1]除了在极少数情况下,参数是一个函数;在这种情况下,结果是一个左值,因为没有函数rvalues。
[1] Except in the rare case in which the argument is a function; in that case the result is an lvalue, since there are no function rvalues.
这篇关于可以reinterpret_cast(或任何演员)将xvalues转换为lvalue?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!