类型转换(Type conversions)
Automatic type conversion (or standard conversion)
当编译器期望一个特定类型的数据但所提供的是别的类型的数据时发生自动类型转换,该过程由编译器执行而非程序员显式指定
留坑:http://en.cppreference.com/w/cpp/language/implicit_conversion
Type casting
两种写法:
double x = 3.14;
int y;
y = int (x); // functional notation
y = (int) x; // c-like cast notation
对于基础类型而言,这种通用形式的类型转换能够满足大部分情况下的需要,但是,当应用在 class 中或者指向 class 的指针中时即是语法上正确运行时可能会出现问题,比如两个毫不相关的类之间的转型。为了控制类之间的转型,C++ 中有四种专用的 casting operator:
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
dynamic_cast
dynamic_cast <new_type> ( expression )
只能用于指向 class 的指针或引用(或void*
),该转型的目的是确保结果指向的是一个目标类型完整、有效的对象。dynamic_cast 自然而然地包含 pointer upcast (从 pointer-to-derived 到 pointer-to-base),pointer upcast 也可允许 implicit conversion。此外,dynamic_cast 也支持对 polymorphic classes (含有 virtual 成员) 的 downcast,前提条件是指向的对象是目标类型的有效完整对象。
如果 dynamic_cast 转型指针时指针所指对象不是要求类型的完整的对象时将返回 null pointer 作为结果表示转型失败,如果对引用进行转型时失败则抛出一个 bad_cast 异常。
dynamic_cast 也可以执行其他允许 implicit conversion 的转型,如 null pointer 之间的转型,将指向任意类型的指针转型为void*
等。
dynamic_cast 使用 RTTI 的信息,因此需要编译器支持,下面总结的 typeid 也是。
static_cast
既可以执行 upcast 又可以执行 downcast。在 runtime 不会执行确保被转型的对象是目标类型的完整对象的检查操作,所以由程序员来确保转型是安全的,因此避免了 dynamic_cast 中花费在类型安全检查上的额外开销。
reinterpret_cast
将指向某种类型的指针转型为指向任意另一种类型的指针,即使是毫不相关的 classes。
const_cast
操作指针所指对象的常量性(constness),添加或去除。注意,消除指针所指对象的常量性之后对其进行写操作会导致未定义行为。
typeid
用来检查表达式的类型。用法:typeid (expression)
,返回const std::type_info
。typeid 返回的值之间可以进行 == 和 != 的比较,也可以调用 name() 方法得到一个表示数据类型或 class name 的 null-terminated 字符串(由实现定义)。
typeid 应用到 classes 时使用 RTTI 来追踪动态对象的类型。当 typeid 应用到一个多态类时结果是 the type of the most derived complete object。
注意,当 typeid 应用到指针时,返回的是它们的类型,而当应用到解指针的表达式时返回的是它们的动态类型,如
Reference
http://www.cplusplus.com/doc/tutorial/typecasting/
What static_cast<> is actually doing
利用 iterator 删除 std::vector 中的元素注意 iterator 的无效值。
for (auto i = v.begin(); i != v.end(); ++i) {
if (*i = blabla) {
v.erase(i);
}
}
这种写法会出错,下面写法不会出错:
for (auto i = v.begin(); i != v.end();) {
if (*i = blabla) {
v.erase(i);
}
else {
++i;
}
}