[Cpp基础] [06] 强制类型转换

  • C++风格的类型转换有四种,每个都有特定的应用场合.转换可以分为隐式或显式的,显式转换也被称为强制类型转换.
    • 隐式类型转换语义上只能对应static_cast或const_cast二者其一.
  • 规定:仅有xxx_cast<TYPE &>(var)整体可以作为左值,其他情况转换得到的都是右值临时对象。

强制类型转换

const_cast

  • const_cast是只用于处理const相关的类型转换,主要是移除const(加const完全可以用隐式转换), const_cast只有向引用/指针的转换有实际意义.
const T c_obj;
const T * p_c_obj=&c_obj;
const T * const cp_c_obj=p_c_obj;
T& wobj=const_cast<T&>(c_obj);//通过引用消const
T * p_wobj=const_cast<T *>(p_c_obj);//消去指向对象的const
const T * & p_c_obj2=const_cast<const T * &>(cp_cobj;)//消去指针自身的const  

static_cast

  • static_cast只用于处理编译期(静态)兼容类型间的类型转换,也就是说,dest类型必须支持从src类型构造.
    • static_cast无法获得运行时信息,只会进行普通的编译期检查.
    • 大部分内置数值类型之间都有预定义好的类型转换方法,彼此是兼容的.(截断/提升等)
    • void *指针和任意指针类型之间都是按照reinterpret的形式兼容的.
  • 原则上,const相关的转换只能由const_cast处理,但是有的编译器可能也会允许static_cast做这些工作

dynamic_cast

  • dynamic_cast只用于处理运行期(动态)类型转换.
    • 只有多态类型有动态类型转换(必须要有vptr,因为运行期类型信息存储在vtable中).
    • 类型转换在运行期执行,如果转换失败,会抛出异常或者返回null指针.
    • 对于非多态类型,typeid()总是获得其静态信息.对于多态类型typeid()可以在运行期获得对象类型.
class A{virtual ~A(){}};
class B:public A{};
void f(A * pA){
    B * pB1=static_cast<B *>(pA);//静态转换,由用户保证pA一定指向一个B型实例
    B * pB2=dynamic_cast<B *>(pA);//动态转换,如果运行时pA指向的不是B型对象,就会报错.
}

reinterpret_cast

  • reinterpret_cast只用于内置数值类型,保证转换前后的二进制值一致.
    • 尤其是指针间的转换.用于保证转换前后的内存数值绝对相同.例如,若C同时继承自A和B,则通过static_cast/dynamic_castC * obj向基类Bcast时,编译器会修改指针指向的地址,这种行为可以由reinterpret_cast抑制.

Read more

Coroutine

从一般概念上说, 协程是特殊的函数调用: 被调用的函数可以在可控的位置被中断,然后在下一次调用时,继续从上次中断的位置继续执行。 本文主要通过Python的协程来介绍协程, 这是我唯一熟悉的一种协程实现. Classic Coroutine 下面的python代码很好的说明了协程的核心功能 def co_routine(): recv0 = yield 996 # hangs here after first coro.send assert recv0 == "Second" yield 711 # hangs here after second coro.send return def main(): coro = co_routine() # Create a new coroutine object value = coro.send(None)

By Edimetia3D

GDB with Python

这篇文章的主要应用场景是调试Python的C/C++ Extension 1. 同时使用pdb / gdb 进行调试. 通俗点说, 既可以break在 .py 文件中,也可以break在 .cc 文件中 2. 在gdb中不但可以获得常规的调试信息, 还可以获得python VM 的调试信息, 例如获得python的调用栈, 访问Python局部变量等. 这将会在调试exception时(如Segmentfalut)非常有用, 这种场景下, 定位 Python VM 正运行到哪一行代码往往可以提供一些直观的重要信息. 第一步: 编译源码以获得一些辅助数据. 我们并不真的需要使用从源码编译的Python, 但是一些调试相关的辅助文件需要从源码中获得, 包括 python-gdb.py及debug symbol等. 在 https://www.python.org/ftp/python/ 或 https://github.com/python/cpython

By Edimetia3D

Bazel Notes

这是一篇2019年左右的记录, 内容可能过时, 也不太全面 杂谈 Bazel是Google为Monorepo服务而开发的构建工具. 首先是巨大,当问题的规模变大,事情总是会变得更复杂. 而Google面对的"巨大Monorepo",应该是世间罕有的. 然后是Monorepo,这极大的影响了代码的组织风格.例如,你要写一个操作系统内核ProjectOS,还要写一个游戏ProjectGame.在传统的开发习惯中,这两个项目会组织到两个不同的Repo里,PorjectOS和ProjectGame之间无法直接相互引用,例如,你在ProjectOS里写了一个高级的数据结构,想要在Game里也使用,要么直接复制粘贴,要么是创建一个新的CommonRepo,把可公用的代码都放在Common里,然后两个项目各自引入Common作为依赖. 使用MonoRepo则不存在这个问题,Game可以直接依赖OS内的组件,按照Bazel的语法描述,就是在Game中可以直接使用@ProjectOS//path/to/package:AdvancedStruct.当然,你仍然可以选择重构一

By Edimetia3D

Unix related things

这是一篇2017年左右的记录, 仅用作分享 杂 * 在shell内能干的事,我们都可以比较简单地通过系统调用实现. * `称为反引号,^称为脱字符,常用来表示CTRL * windows的系统调用是不开放的,windows下只能直接使用windows.h里的windows API. * /dev目录下的设备是供用于程序直接使用的,主要由block,char,pipe,socket类型 * 并不是所有设备都能映射为这种形式 * /sys/device/目录称为sysfs,他下面存放了所有设备的信息.(不能直接从/dev获得任何设备信息) * udevadm info --query=all --name="/dev/sda1"可以用于查询/dev下某个设备对应的sysfs路径 权限系统 * 权限系统由两部分组成 * 文件属性:用于标注文件owner,所属组,以及权限的设定(默认只有owner和root可以修改权限设置) *

By Edimetia3D