四个强制类型转换reinterpret_castconst_caststatic_cast dynamic_cast及比较

news/2024/7/7 20:42:46

四个强制类型转换reinterpret_cast/const_cast/static_cast /dynamic_cast及比较

reinterpret_cast

reinterpret_cast 是一种 C++ 转换运算符,允许程序员在不更改原始对象的情况下将指针或引用转换为不同的类型。 它是一个非常强大且具有潜在危险的运算符,应谨慎使用。

reinterpret_cast 运算符可用于在指针和不相关类型的引用之间进行转换,或将数据对象的位重新解释为不同的类型。 这是一个例子:

int i = 42;
float* fp = reinterpret_cast<float*>(&i);

在此示例中,我们有一个值为 42 的整数“i”。然后我们使用“reinterpret_cast”创建一个指向浮点数“fp”的指针,它获取“i”的地址并将其视为指向“浮点数”的指针。 这意味着 fp现在指向与i相同的内存位置,但将i的位视为float`

请注意,reinterpret_cast 不执行任何类型检查或转换。 它只是将对象的位重新解释为不同的类型。 这意味着错误地使用“reinterpret_cast”会导致未定义的行为,例如读取或写入无效的内存位置。

因此,“reinterpret_cast”只应在绝对必要时使用,并且要透彻了解所涉及的类型和潜在风险。

const_cast

const_cast 是一种 C++ 转换运算符,允许程序员删除或添加变量或对象的常量。 当程序员想要修改声明为“const”的变量或对象,或将“const”添加到非 const 变量或对象时,会使用它。

这是一个例子:

void print(int* ptr) {
    std::cout << *ptr << std::endl;
}

int main() {
    const int i = 42;
    const int* ptr = &i;
    int* ptr2 = const_cast<int*>(ptr);
    *ptr2 = 7;
    print(const_cast<int*>(ptr));
    return 0;
}

在此示例中,我们有一个值为 42 的常量整数“i”和一个指向“i”的指针“ptr”。 我们使用 const_cast 创建一个非常量指针 ptr2 指向与 ptr 相同的内存位置。 然后我们通过将 ptr2 设置为 7 来修改 i 的值。

print 函数接受一个指向整数的非常量指针并打印它的值。 我们再次使用 const_cast 将 ptr(常量指针)传递给 print。

请注意,使用 const_cast 修改 const 对象可能很危险,应谨慎操作。 修改 const 对象可能会导致未定义的行为和意外结果,因此只有在必要时才应该这样做。

static_cast

static_cast 是一种 C++ 转换运算符,允许程序员执行已知在编译时安全的类型转换。 它可用于相关类型之间的转换,例如将派生类指针转换为基类指针,或执行算术转换,例如将整数转换为浮点数。

这是一个例子:

int main() {
    int i = 42;
    float f = static_cast<float>(i);
    std::cout << f << std::endl;

    Base* base = new Derived();
    Derived* derived = static_cast<Derived*>(base);
    derived->doSomething();

    return 0;
}

在此示例中,我们有一个值为 42 的整数“i”。我们使用“static_cast”将“i”转换为浮点数“f”,这是安全的,结果是“f”的值为 42.0。

我们还有一个基类“Base”和一个派生类“Derived”,并创建一个“Derived”类型的新对象并将其赋值给一个“Base*”类型的指针。 然后我们使用 static_castBase* 指针转换为 Derived* 指针,这是安全的,因为我们知道指向的对象实际上是一个 Derived 对象。 然后我们可以通过 Derived* 指针调用 Derived 类的 doSomething() 函数。

请注意,static_cast 是一个编译时运算符,因此它无法执行运行时安全检查。 仅当程序员确定转换是安全的时才应使用它。 如果对转换的安全性有任何疑问,则应改用“dynamic_cast”。

dynamic_cast

dynamic_cast 是一种 C++ 转换运算符,它允许程序员在运行时执行多态类型的安全向下转换。 当需要将基类指针或引用转换为派生类指针或引用时使用它,但程序员不确定转换是否安全。

这是一个例子:

class Base {
public:
    virtual void doSomething() {
        std::cout << "Base doing something" << std::endl;
    }
};

class Derived : public Base {
public:
    void doSomething() override {
        std::cout << "Derived doing something" << std::endl;
    }
};

int main() {
    Base* base = new Derived();
    Derived* derived = dynamic_cast<Derived*>(base);
    if (derived) {
        derived->doSomething();
    } else {
        std::cout << "Invalid cast" << std::endl;
    }
    delete base;
    return 0;
}

在这个例子中,我们有一个基类“Base”和一个派生类“Derived”。 我们创建一个 Derived 类型的新对象,并将其分配给 Base* 类型的指针。 然后我们使用 dynamic_castBase* 指针转换为 Derived* 指针。 如果转换成功,我们通过 Derived* 指针调用 Derived 类的 doSomething() 函数。 如果转换不成功,我们会打印一条错误消息。

请注意,dynamic_cast 是一个运行时运算符,因此它可以执行检查以确保转换是安全的。 只有在至少具有一个虚函数的多态类上使用“dynamic_cast”才是安全的。 此外,dynamic_cast 只能用于转换指针或引用,不能用于转换对象。

如果转换不安全,dynamic_cast 为指针返回一个空指针或为引用抛出 std::bad_cast 异常。 因此,在使用指针或引用之前检查“dynamic_cast”的结果很重要。

比较

reinterpret_castconst_caststatic_castdynamic_cast 都是用于类型转换的 C++ 转换运算符。 但是,它们在功能和用法上有所不同:

  • reinterpret_cast 是一个非常强大的低级运算符,允许程序员重新解释对象的位,就好像它是不同的类型一样。 它用于在不相关类型的指针和引用之间进行转换,或者将数据对象的位重新解释为不同的类型。 它不执行任何类型检查或转换,应谨慎使用。

  • const_cast 用于删除或添加变量或对象的 const-ness。 它用于修改声明为 const 的变量或对象,或将 const 添加到非 const 变量或对象。

  • static_cast 用于执行已知在编译时安全的安全类型转换。 它可用于相关类型之间的转换,例如将派生类指针转换为基类指针,或执行算术转换,例如将整数转换为浮点数。

  • dynamic_cast 用于在运行时执行多态类型的安全向下转换。 当需要将基类指针或引用转换为派生类指针或引用时使用它,但程序员不确定转换是否安全。 它执行运行时检查以确保转换是安全的,并返回空指针或抛出 std::bad_cast 异常(如果不是)。

通常,应谨慎使用 reinterpret_castconst_cast,因为如果使用不当,它们很容易导致未定义的行为。 在执行已知在编译时安全的类型转换时,static_cast 是更安全的选择,而在运行时执行多态类型的向下转换时,dynamic_cast 是最安全的选择。


http://lihuaxi.xjx100.cn/news/1243272.html

相关文章

深入剖析@RequestBody、@PathVariable和@RequestParam注解

当我们在开发服务端方法时&#xff0c;遇到给方法传参的有几个不同的注解&#xff0c;今天我们来介绍 RequestBody、PathVariable 和 RequestParam 这几个注解的定义和使用场景示例&#xff0c;以便于同学们理解和掌握。 RequestBody 注解&#xff1a; 定义&#xff1a; Reques…

CVE-2023-0215

mysql 安全漏洞 生产版本&#xff1a;5.5 漏洞编号&#xff1a; CVE编号 CVE-2023-0215 CNNVD编号 CNNVD-202302-521 另外还有以下其他漏洞&#xff1a; 解决办法&#xff1a; 1.下载补丁需要CSI,买了oracle服务才可能会有这个认证码&#xff1b; 2.没有这个认证码&#…

阿里云PAIx达摩院GraphScope开源基于PyTorch的GPU加速分布式GNN框架

作者&#xff1a;艾宝乐 导读 近期阿里云机器学习平台 PAI 团队和达摩院 GraphScope 团队联合推出了面向 PyTorch 的 GPU 加速分布式 GNN 框架 GraphLearn-for-PyTorch(GLT) 。GLT 利用 GPU 的强大并行计算性能来加速图采样&#xff0c;并利用 UVA 来减少顶点和边特征的转换和…

【数据结构】数据结构与算法基础 课程笔记 第八章 排序

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;【数据结构】 &#x1f4ac;总结&#xff1a;希望看完之后&#xff0c;能…

ROS-melodic:源码安裝teb_local_planner算法、替换DWA算法

一.安裝teb_local_planner算法 源码下载地址&#xff1a;GitHub - rst-tu-dortmund/teb_local_planner: An optimal trajectory planner considering distinctive topologies for mobile robots based on Timed-Elastic-Bands (ROS Package) 注意选择对应ROS版本的代码。 放在…

作为一个优秀的项目经理,你需要做什么?

经常看到这样的项目经理&#xff0c;一副整天忙得团团转的样子&#xff0c;整天忙得团团转&#xff0c;发出一大堆指令&#xff0c; 经常事无巨细都要亲自过问&#xff0c;他还会不断抱怨说&#xff1a; " 我很忙 " 或 " 我很累 " &#xff0c; " 我…

AB32VG1:SDK_AB53XX_V061(5)蓝牙BLE测试笔记

文章目录 1.配置工程&#xff0c;重新编译1.1替换链接库libbtstack_dm.a1.2 《config.h》打开编译开关1.3 在 Downloader 里面打开 BLE 开关 2.ABLink&#xff08;手机APP&#xff09;控制2.1 app下载2.2 安装后打开&#xff0c;搜索蓝牙Bluetrum&#xff1a;2.3 操作存储卡 3.…

通讯基站电源智能监控系统

通信基站又称无线基站&#xff0c;一般都安装在宽阔、偏远的地方&#xff0c;且分散&#xff0c;实现人工值守十分困难&#xff0c;成本高&#xff1b;另外局部内动力设备、蓄电池电源以及环境无法及时监视和控制&#xff0c;造成事故频发。然而蓄电池作为直流备用电源&#xf…