Ser*_*gei 8 c++ templates reinterpret-cast
我有一个类模板A,其中包含一个指针容器(T*):
template <typename T>
class A {
public:
// ...
private:
std::vector<T*> data;
};
Run Code Online (Sandbox Code Playgroud)
和一堆功能,如:
void f(const A<const T>&);
void g(const A<const T>&);
Run Code Online (Sandbox Code Playgroud)
是否可以将呼叫通过铸造这些功能从A<const T>到A<T>?
A<double> a;
...
auto& ac = reinterpret_cast<const A<const double>&>(a);
f(ac);
Run Code Online (Sandbox Code Playgroud)
我很确定这段代码有不确定的行为.
在现实生活中使用这种转换是危险的吗?
作为A<double>和A<const double>不相关类型,它实际上未指定的(原本我以为未定义)行为和相应的是这是一个坏主意,在现实生活中使用:你永远不知道什么系统(S)或编译器(S),你可以移植到这种变化的行为是奇怪的方式。
参考:
5.2.10/11:
如果可以使用 reinterpret_cast 将“指向 T1 的指针”类型的表达式显式转换为“指向 T2 的指针”类型,则可以将 T1 类型的左值表达式转换为“对 T2 的引用”类型。也就是说,引用转换 reinterpret_cast(x) 与转换 *reinterpret_cast(&x) 与内置 & 和 * 运算符具有相同的效果(对于 reinterpret_cast(x) 也是如此)。
所以他们把我们重定向到了之前的 5.2.10/7 节:
对象指针可以显式转换为不同类型的对象指针。... ... 将“指向 T1 的指针”类型的纯右值转换为“指向 T2 的指针”类型(其中 T1 和 T2 是对象类型,并且 T2 的对齐要求不比 T1 的对齐要求严格)并返回到它的原始类型产生原始指针值。任何其他此类指针转换的结果是未指定的。
如果f和g是适用于容器的算法,简单的解决方案是将它们更改为适用于范围(迭代器对)的模板算法。
虽然reinterpret_cast本身可能是未指定的行为,但是在完成转换后尝试访问参数是未定义的行为.
N3337 [basic.lval]/10:如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义- 对象的动态类型,
- 对象的动态类型的cv限定版本,
- 与对象的动态类型类似的类型(如4.4中所定义),
- 与对象的动态类型对应的有符号或无符号类型的类型,
- 对应于对象的动态类型的cv限定版本的有符号或无符号类型,
- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
- 一种类型,是对象的动态类型的(可能是cv限定的)基类类型,
- char或unsigned char类型.
你的例子不是上述例子.