C++:const_cast

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

    const_cast是一个运算符,和dynamic_cast、static_cast、reinterpret_cast一样都是用于类型的转换的,本来想将这四个一起写的,但是查了const_cast相关的资料,发现const_cast可以牵扯到的也不少,所以单独用一篇博客说明了。

1. 用法

     const_cast的作用很简单,就是去除或增加类型中的const属性或volatile属性,注意这里也可以用于增加这两种属性。其原型如下:

const_cast<type_id> (expression)

     虽然这里用了“去除”,但实际上并没有改变原类型的const属性或volatile属性,而是提供了一个接口(指针或引用),使得我们可以通过这个新的接口(变量)来改变原类型的值。在const_cast中,type_id也只能是指针或者引用,因为只有通过指针或引用才能得到原类型的地址,从而对其内存内容进行修改。

    个人觉得const_cast就有点类似于显式类型转换,将原来变量起了新的别名或者将其地址赋给新另一个指针,只不过它是限定源类型和目的类型是要一样的。更详细的介绍可以看这里:const_cast 转换

    下面是使用的例子:

#include <iostream>

using namespace std;

int main()
{
    const int a = 10;
    // 强制转换
    int *p = (int *)(&a);
    *p = 20;
    cout << "a = " << a << ", *p = " << *p << endl;
    // const_cast到指针
    int *p2 = const_cast<int *>(&a);
    *p2 = 30;
    cout << "a = " << a << ", *p = " << *p << endl;
    // const_cast到引用
    int &p3 = const_cast<int &>(a);
    p3 = 40;
    cout << "a = " << a << ", *p = " << *p << endl;

    return 0;
}

        上面举出了三种转换的方法,第一种是将取地址后保存,后面两种则分别用了const_cast的指针和引用方式,这三种方式都可以修改const变量a对应内存的内容。但是上面程序的输出却可能与我们想象中的不一样:

a = 10, *p = 20
a = 10, *p = 30
a = 10, *p = 40

        可以看到,即使设置“*p = 20”、“*p2 = 30”、“p3 = 40”,在三次输出中,a的值都是最初定义的值10,并没有改变,这是为什么呢?原因就在于接下来要介绍的概念:常量折叠。

2. 常量折叠(const folding)

      常量折叠与编译器的工作原理有关,是编译器的一种编译优化。在编译器进行语法分析的时候,将常量表达式计算求职,并用求得的值来替换表达式,放入常量表。所以在上面的例子中,编译器在优化的过程中,会把碰到的a(为const常量)全部以内容10替换掉,跟宏的替换有点类似。

      与常量折叠紧关的概念是复写传播(copy propagation),这里就不讲了。

      虽然在运行阶段a的内容确实是被改变了,但它在打印的部分已被替换为10了,导致打印出来的值与我们期望的就不一样了。这让我想到在收集资料时看到的这句话:

const是一个编译时约定,而不是运行时约定。

      另外,常量折叠只对原生类型其作用,对我们自定义的类型,是不会起作用的。下面是我测试的例子:

#include <iostream>
#include <stdio.h>

using namespace std;

typedef struct _Test {
    int a;
    _Test() {
        a = 10;
    };
} Test;

int main()
{
    const Test b;

    Test *b1 = const_cast<Test *>(&b);
    cout << "b = " << b.a << endl;
    b1->a = 100;
    cout << "b = " << b.a << ", *b1 = " << b1->a << endl;

    return 0;
}

      输出内容如下:

b = 10
b = 100, *b1 = 100

      可以看到对于自定义的类型,是不存在常量折叠的想象的,估计是对于自定义类型并不会进行相应的优化操作吧。

3. const_cast的使用场景

      正常情况下,当我们在创建变量时加上const关键字则说明我们是不希望他被改变的,不加上const则表明我们存在改变它的可能性。那const_cast究竟在什么情况下会用到呢?因为正常情况下我们写代码函数什么的肯定是对变量的修改情况有了解的。

     经过搜索,发现const_cast似乎是应该用在这种情况的:假如函数A中调用B函数,B中定义参数是const的而A传入的变量是非const,这个时候我们就可以用const_cast给传入的变量加上const属性了。反过来B中定义参数是非const而A传入的变量是const的,则我们可以用const_cast将传入变量的const属性去掉了(当然这种情况下就算不加const属性也是可以的)。

#include <iostream>

using namespace std;

void not_const_char(char *str)
{
    cout << str + 5 << endl;
}

void const_char(const char *str)
{
    cout << str + 5 << endl;
}

int main()
{

    const char str[] = "abcdefgggg";
    char str1[] = "efggggeeee";

    not_const_char(str1);       // ok
    // not_const_char(str);   //  compile fail
    not_const_char(const_cast<char *>(str));   //  ok

    const_char(str1);       // ok
    const_char(str);   // ok

    return 0;
}

       可以看到注释掉的调用“not_const_char(str)”是编译失败的,也就是说如果将const属性的变量传入到非const的函数中,编译不会通过(const是编译时约定,它预期在传入的函数中会对其内容修改),但用const_cast对传入的变量去掉const属性后再传入,就能正常编译通过了。

      搜索了下公司的项目代码,简略看到有两种情况用到了const_cast。

      第一种是在单例模式中的函数修改类中的静态成员对象时:

const_cast<SomethingStatistic&>(statistic_).inc_recv_num();

     第二种如下:

void App::Fish(uint64_t id, const char* data, uint32_t len) {
    ...
        reinterpret_cast<CHeader*>(const_cast<char*>(data) +
                                        sizeof(FHead) - sizeof(CHeader));
    ...
}

       第一种我也不太理解,但看到在protobuf的源码中也有类似的用法,希望有懂的人可以说明下。第二种就有点类似于我上面所举的例子,只是这里需要对data数据转换成需要的类型:CHeader是非const,而传入的data是const的,所以在需要去掉data的const属性吧。

 

 

      以上是全部内容,学无止境,说得不对的请指正,有什么更深的了解也希望大家能在评论里说出来。

const_cast 详解及使用场景 C++ 中最危险的类型转换之一,必须谨慎使用。在大多数情况下,有更好的替代方案。​ 的类型转换运算符。它是唯一能够移除 const 属性的 C++ 风格转换。:尽量少用,优先考虑 mutable 和更好的设计。是 C++ 中专门用于添加或移除变量的。你确切知道对象不是真正的 const。(在 const 函数中修改缓存):充分测试,确保不会导致未定义行为。转换后不会违反 const 正确性。(需要移除 const 限定符):添加注释说明为什么必须使用。有充分的理由不使用其他方法。(确认不会修改数据) 阅读详情

相关推荐

英飞凌TLF35584 SBC实战:手把手教你配置WDG看门狗与ERR监控(基于AUTOSAR架构)

本文详细介绍了基于AUTOSAR架构的英飞凌TLF35584 SBC芯片WDG看门狗与ERR监控功能的配置方法。通过硬件平台搭建、寄存器级配置、AUTOSAR模块集成及诊断策略优化,帮助开发者快速掌握关键配置技巧,提升嵌入式系统的安全性和可靠性。

weixin_30256901的博客 445

C++新特性06_强制转换运算符_const_cast(强制转换运算符:需要类型转换的时候使用,用于用编译器实现检测;const_cast:仅用于进行去除const 属性的转换;内存中?代表不可访问)

强制类型转换是有一定风险的,有的转换并不一定安全,如把整型数值转换成指针,把基类指针转换成派生类指针,把一种函数指针转换成另一种函数指针,把常量指针转换成非常量指针等。 1.C语言中强转的方法: int n = 1; //将n的地址赋给指针p //int* p = &n; //c语言中进行强制转换,将n作为一个地址赋给p //p是带有类型的地址 int* p = (int*)n; 当对地址为1的p进行访问的时候,会报如下错误: int main() { int n = 1

分享学习成长历程,Winter is coming! 6261

C语言实现贪吃蛇小游戏!(超简单详细)详细思路+源码分享

我们的今天的目标就是:用C语言来实现一个贪吃蛇项目,也不用太复杂,初学者能看懂就行!

致力于C语言C++知识分享! 1万+

C++const_cast 作用详解

const_cast是一种C++运算符,主要是用来去除复合类型中const和volatile属性(没有真正去除)。 我们需要注意的是:变量本身的const属性是不能去除的,要想修改变量的值,一般是去除指针(或引用)的const属性,再进行间接修改。 用法:const_cast<type>(expression) 通过const_cast运算符,也只能将const type*转换为type*,将const type&转换为type&。 也就是说源类型和目标类型除了const

weixin_44218779的博客 1万+

C++const_cast基本用法(详细讲解)

👉博__主👈:米码收割机👉技__能👈:C++/Python语言👉公众号👈:测试开发自动化【获取源码+商业合作】👉荣__誉👈:阿里云博客专家博主、51CTO技术博主👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。

测试开发自动化 5907

const_cast

因此,仅在确实必要,且明确知道自己在做什么的情况下,才使用。属性并修改变量的值,虽然在技术上是可行的,但在逻辑上可能是不安全的。关键字表示变量的值不应该被改变,直接修改这样的变量会导致编译错误。通常,在编程过程中,我们可能会遇到需要修改一个被声明为。然而,需要强调的是,这种做法应该非常谨慎地使用。属性的目标类型,而“表达式”则是指向原始数据的指针或引用。进行修改,可能会导致程序行为的不可预测性和潜在的错误。是C++中的一个类型转换运算符,专门用于去除变量的。的指针,你希望能够通过这个指针修改所指向的。

weixin_39291964的博客 1527

C++ 强制类型转换:static_cast、dynamic_castconst_cast 和 reinterpret_cast

C++ 强制类型转换:static_cast、dynamic_castconst_cast 和 reinterpret_cast

Dong_HFUT的博客 9468

C++C++ 的四种强制类型转换 static_cast、dynamic_castconst_cast、reinterpret_cast

在上面所有形式中,e 的类型必须符合以下三个条件中的任何一个:e 的类型是是目标类型 type 的公有派生类、e 的类型是目标 type 的共有基类或者 e 的类型就是目标 type 的的类型。前两个的输出值是相同的,最后一个则会在原基础上偏移 4 个字节,这是因为 static_cast 计算了父子类指针转换的偏移量,并将之转换到正确的地址(c 里面有 m_a,m_b,转换为 B * 指针后指到 m_b 处),而 reinterpret_cast 却不会做这一层转换。这种转换的安全性也要开发人员来保证。

weiweiqiao的专栏 3594

C++语法|C++的类型转换:const_cast、static_cast、reinterpret_cast、dynamic_cast

由于我们的derive02func()是新写的函数,基类中也不存在该虚函数,所以只能是静态绑定,我们也只能通过Derive2类型的指针来进行访问。dynamic_cast往往用在继承结构中,特别是存在虚函数表的情况下,该方法对于统一接口的改进,使得多态能够变得更加灵活。我们可以使用C风格的方式进行类型转换,我们也可以用C++风格的类型转换,想把它转成什么类型,尖括号<>就写什么类型。此时我们需要关注 *p的类型,当它是Derive2类型的,我们就需要去调用。

糖炒栗子 984

C/C++中类型转换:static_cast, dynamic_cast, const_cast, reinterpret_cast

提供安全的基本类型转换:但是要注意数据的截断或者改变。(float转换为整数的时候丢失小数部分)。向上转换(将派生类的指针/引用转换为基类的指针/引用),这是安全的,因为派生类总是包含基类的全部信息。向下转换(将基类的指针/引用转换为派生类的指针/引用),这是不安全的,因为基类不一定包含派生类的全部信息。空指针转换为目标类型的空指针:class Base {};// 安全转换,d 仍然是 nullptr。(b);// 安全转换,d 仍然是 nullptr。

qq_40837128的博客 1215

C++类型转换深度解析:static_cast、dynamic_castconst_cast、reinterpret_cast实战指南

类型转换是编程语言中处理不同数据类型间相互操作的基础机制,其核心原理是在保持数据语义的前提下实现内存表示的重新解释或数值的变换。在C++中,类型系统作为安全基石,类型转换技术直接关系到程序的内存安全、性能优化与代码可维护性。C++提供了四种命名的强制类型转换操作符——static_cast、dynamic_castconst_cast和reinterpret_cast,每种都针对特定场景设计,旨在替代C语言中不安全的隐式转换。从编译期确定的算术转换与类层次向上转型,到运行时的多态类型安全探测,再到底层内存

weixin_33901926的博客 421

掌握C++类型转换:static_castconst_cast、dynamic_cast 和 reinterpret_cast

静态类型转换静态类型转换是最常用的类型转换方式,它可以将一种类型的数据强制转换为另一种类型,但需要注意的是,这种转换可能会损失一些信息,因此在进行此类转换时应当谨慎。int a = 10;动态类型转换动态类型转换主要用于多态类型之间的转换,它可以将基类指针或引用转换为派生类指针或引用。如果进行非法的类型转换,动态类型转换会返回一个空指针。重新解释类型转换。

Lion_Long的博客 6376

C++强制运算符:static_castconst_cast

强制转换运算符是一种特殊的运算符,它把一种数据类型转换为另一种数据类型。强制转换运算符是一元运算符,它的优先级与其他一元运算符相同。 大多数的 C++ 编译器都支持大部分通用的强制转换运算符: (type) expression 其中,type 是转换后的数据类型。下面列出了 C++ 支持的其他几种强制转换运算符: const_cast (expr): const_cast 运算符用于修改类型的 const / volatile 属性。除了const 或 volatile 属性之外,目标类型必须与源

xiaojinger_123的博客 2272

C++类型转换:static_castconst_cast、reinterpret_cast、dynamic_cast

C++提供了四种类型转换操作符替代C风格强制转换:static_cast用于基础类型转换和继承体系向上转换,编译时检查;dynamic_cast用于多态类安全向下转型,运行时检查;const_cast用于修改const/volatile属性;reinterpret_cast用于底层位操作和指针转换,风险最高。这些转换操作符比C风格转换更安全明确,应优先使用。

qq_71320435的博客 1027

c++强制类型转换:dynamic_castconst_cast 、static_cast、reinterpret_cast

dynamic_cast:   通常在基类和派生类之间转换时使用,run-time   castconst_cast:   主要针对const和volatile的转换. static_cast:   一般的转换,no   run-time   check.通常,如果你不知道该用哪个,就用这个。   reinterpret_cast:   用于进行没有任何关联之间的转换,比如一个字符指针转换为一

人在旅途/章鸽 的专栏 2万+

C++ : 四种类型转换(static_cast,reinterpret_castconst_cast,dynamic_cast

综上,我们可以看到隐式类型转换的缺陷:转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换,c++提出了自己的四种转换,可以有效的处理这些问题。,它在静态区开空间进行存储数据,变量被const进行修饰具有常性,数据不可以被修改,但是我们可以通过类型转换,通过指针去修改它存储的数据的值,但是这种修改数据的值的方式是存在安全隐患的,因为我们使用const进行修饰变量,就是不希望数据被修改。关键字进行修饰变量,被volatile修饰的变量,编译器在取它的值的时候,每次都会去内存中去取。

2402_87310323的博客 1146

C++类型转换深度解析:static_cast、dynamic_castconst_cast与reinterpret_cast实战指南

类型转换是编程中处理不同数据类型间操作的基础机制,其核心原理在于改变编译器对内存中二进制数据的解释方式。在C++等强类型语言中,合理的类型转换技术能提升代码的类型安全性和可维护性,避免未定义行为。从技术价值看,C++引入的四种具名转换操作符(static_cast、dynamic_castconst_cast、reinterpret_cast)分别针对不同场景,将原本笼统的转换意图显式化,使编译器能进行更严格的检查。这些转换在面向对象编程、多态处理、底层系统编程和API兼容等应用场景中至关重要。例如,dy

weixin_34275734的博客 322

C++四种类型转换运算符:static_cast、dynamic_castconst_cast和reinterpret_cast

隐式类型转换是安全的,显式类型转换是有风险的,C语言之所以增加强制类型转换的语法,就是为了强调风险,让程序员意识到自己在做什么。 但是,这种强调风险的方式还是比较粗放,粒度比较大,它并没有表明存在什么风险,风险程度如何。再者,C风格的强制类型转换统一使用( ),而( )在代码中随处可见,所以也不利于使用文本检索工具(例如 Windows 下的 Ctrl+F、Linux 下的 grep 命令、Mac...

7TribeZ的博客 3862

标准C++的类型转换符:static cast、dynamic cast、reinterpret castconst cast

C 风格(C-style)强制转型 (T) exdivssion // cast exdivssion to be of type T 函数风格(Function-style)强制转型使用这样的语法: T(exdivssion) // cast exdivssion to be of type T 这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。我把这两种形式称为

FengDeveloper的专栏 955

c++智能指针转化:static_pointer_cast、dynamic_pointer_castconst_pointer_cast、reinterpret_pointer_cast

C++基类和派生类的智能指针转换:static_pointer_cast、dynamic_pointer_castconst_pointer_cast、reinterpret_pointer_cast 当我们用“裸”指针进行类层次上的上下行转换时,可以使用dynamic_cast。当然我们也可以使用static_cast,只是dynamic_cast在进行下行转换的时候(即基类到派生类)具有类型检查功能,而static_cast没有。因此存在安全问题。 当我们使用智能指针时,如果需要进行类层次上的上下

sunlin972913894的博客 3万+

c++智能指针转化:static_pointer_cast、dynamic_pointer_castconst_pointer_cast、reinterpret_pointer_cast 相关函数梳

它们的功能和std::static_cast()、std::dynamic_cast、std::const_cast()和std::reinterpret_cast()类似,只不过转换的是智能指针std::shared_ptr,返回的也是std::shared_ptr类型。由于std::dynamic_pointer_cast和dynamic_cast原理一样,std::static_pointer_cast和static_cast原理一样。)才能允许动态强制转换,否则编译报错)。

hnjzfwy的博客 1190
上一篇: 面试:杂记(一)
下一篇: C++:map、hash_map、unordered_map
cylianging
博客等级 码龄13年 21粉丝 68原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值