reinterpret_cast 会导致未定义的行为吗?
我有一个类模板 A
,它包含一个指针容器 (T*
):
I have a class template A
which contains a container of pointers (T*
):
template <typename T>
class A {
public:
// ...
private:
std::vector<T*> data;
};
还有一堆函数,比如:
void f(const A<const T>&);
void g(const A<const T>&);
是否可以通过从 A
到 A
的强制转换来调用这些函数?
Is it OK to call these functions via a cast from A<const T>
to A<T>
?
A<double> a;
...
auto& ac = reinterpret_cast<const A<const double>&>(a);
f(ac);
我很确定这段代码有未定义的行为.
I'm pretty sure that this code has undefined behaviour.
在现实生活中使用此类转换是否危险?
Is it dangerous to use such conversions in real life?
推荐答案
由于 A
和 A
是不相关的类型,它实际上是未指定的(最初我认为未定义的)行为,相应地,在现实生活中使用它是一个坏主意:你永远不知道你可以移植什么系统或编译器来改变行为是奇怪的方式.
As A<double>
and A<const double>
are unrelated types, it's actually unspecified (originally I thought undefined) behavior and correspondingly yes it's a bad idea to use in real life: You never know what system(s) or compiler(s) you may port to that change the behavior is strange ways.
参考:
5.2.10/11:
T1 类型的左值表达式可以转换为引用到T2",如果指向 T1 的指针"类型的表达式可以显式表示使用 reinterpret_cast 转换为指向 T2 的指针"类型.那即,参考强制转换 reinterpret_cast(x) 具有相同的效果使用内置的 & 转换 *reinterpret_cast(&x)和 *运算符(与 reinterpret_cast(x) 类似).
An lvalue expression of type T1 can be cast to the type "reference to T2" if an expression of type "pointer to T1" can be explicitly converted to the type "pointer to T2" using a reinterpret_cast. That is, a reference cast reinterpret_cast(x) has the same effect as the conversion *reinterpret_cast(&x) with the built-in & and * operators (and similarly for reinterpret_cast(x)).
所以他们将我们重定向到了之前的 5.2.10/7 部分:
So they've redirected us to an earlier section 5.2.10/7:
对象指针可以显式转换为一种不同的类型.... ... 转换类型的纯右值指向 T1 的指针"指向指向 T2 的指针"类型(其中 T1 和 T2 是对象类型和 T2 的对齐要求没有的地方比 T1) 更严格并返回到其原始类型产生原始指针值.任何其他此类指针的结果转换未指定.
An object pointer can be explicitly converted to an object pointer of a different type. ... ... Converting a prvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
如果 f
和 g
是适用于容器的算法,那么简单的解决方案是将它们更改为适用于范围(迭代器对)的模板算法.
If f
and g
are algorithms that work on containers, the easy solution is to change them to template algorithms that work on ranges (iterator pairs).
相关文章