在生产代码中删除dynamic_cast是安全的吗?
Are dynamic_casts safe to remove in production code?
dynamic_cast
s比较慢,但是它们比static_cast
s更安全(当然,当与对象层次结构一起使用时)。我的问题是,在我的调试代码中确保所有(动态)类型转换都是正确的之后,我有任何理由不将它们更改为static_cast
s吗?
我计划用下面的构造来做这件事。(顺便说一句,你能想到一个比assert_cast
更好的名字吗?也许是debug_cast
?)
#if defined(NDEBUG)
template<typename T, typename U>
T assert_cast(U other) {
return static_cast<T>(other);
}
#else
template<typename T, typename U>
T assert_cast(U other) {
return dynamic_cast<T>(other);
}
#endif
Edit: Boost已经有了这个:polymorphic_downcast
。感谢PlasmaHH指出这一点。
不!dynamic_cast
做的不仅仅是投射。它可以检查对象的运行时类型。但是,它也可以遍历编译器不知道但只有在运行时才知道的层次结构。static_cast
不能这样做。
class A1
{
virtual ~A1() {}
};
class A2
{
virtual ~A2() {}
};
class B : public A1, public A2
{ };
A1 *a1 = new B;
A2 *a2 = dynamic_cast<A2*>(a1); //no static_cast!
A1 *x = ...;
if (B *b = dynamic_cast<B*>(x)) //no static_cast!
/*...*/;
您应该断言dynamic_cast
成功:
template<typename T, typename U>
T *assert_cast(U *other) {
T *t = dynamic_cast<T>(other);
assert(t);
return t;
}
替换dynamic_cast
与static_cast
的情况下,当你确定它们是等效的是相同的删除null检查指针,你确定总是非空。出于性能考虑,您可以这样做。
只要您测试了运行时因素/变量/输入的所有可能组合,就可以。正如在注释中提到的,这类似于删除断言。
语言中没有任何东西会使它本质上不安全,只要保证强制类型转换总是正确的。但它确实让人感觉不安全,因为你可能永远无法做出这样的保证。
更新
Konstantin已经证明,在处理多重继承时,这种技术只适用于在继承树1上/下的单个步骤。
struct A1 { virtual ~A1() {} };
struct A2 { virtual ~A2() {} };
struct A3 { virtual ~A3() {} };
struct B : A1, A2 {};
struct C : A1, A3, A2 {};
int main() {
A1* a1 = (rand() < RAND_MAX / 2 ? (A1*)new B : (A1*)new C);
A2* p1 = dynamic_cast<A2*>(a1);
// ^ succeeds, but is a cross-cast
// A2* p2 = static_cast<A2*>(a1);
// ^ ill-formed
A2* p3 = static_cast<A2*>(static_cast<B*>(a1));
// ^ must chain, instead.
// but p3 is invalid because we never
// checked that `dynamic_cast<B*>(a1)` is valid.. and it's not
// Instead, let's expand the `dynamic_cast`s into a chain, too:
A2* p3 = dynamic_cast<B*>(a1);
A2* p4 = dynamic_cast<A2>*(a1);
// ^ p3 fails, so we know that we cannot use `static_cast` here
}
因此,您可以将dynamic_cast
s替换为static_cast
s iff:
- 每个
dynamic_cast
只执行一次单次升压; - 每个
dynamic_cast
已知总是成功的。
1实际上这是一个简化,例如,向下转换将适用于任何数量的步骤。但这是一个很好的经验法则。
之后,我在调试代码中确保所有(动态)强制转换都是正确的对,我有什么理由不把它们改成static_casts吗?
恕我直言,如果您100%确定所有 dynamic_cast<>
都是正确的,那么没有理由不将它们更改为static_cast<>
。可以更改。
我想这取决于项目。如果是核电站管理软件,我更喜欢安全,如果是3D游戏,我更喜欢性能。您永远无法确保所有dynamic_cast
在生产代码中都是正确的。
- 从不同线程使用int64的不同字节安全吗
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 如何理解C++标准N3337中的expr.const.cast子句8
- 虚拟决赛作为安全
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何将元素添加到数组的线程安全函数?
- C++Cast运算符过载
- C++中的线程安全删除
- 通过网络、跨平台传递std::变体是否安全
- 在std::thread中,joinable()然后join()线程安全吗
- 使用std::istream::peek()总是安全的吗
- 从值小于256的uint16到uint8的Endian安全转换
- 在c++队列中使用pop和visit实现线程安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 安全到标准:移动会员?
- AcquireCredentialsHandleA() 返回 PFX 文件的0x8009030e(安全包中没有可用的凭据
- 共享队列的线程安全
- 重新解释cast<是否安全;bool*>清空内存