const_cast的使用:添加或去掉const、常量折叠

避免未定义行为(使用引用时的未定义行为)

一个变量在使用const_cast去掉指针或者引用的const限定符后,“如果常量本身不是常量,获得的权限是合法的, 如果本身是常量,使用const_cast再写的后果是未定义的。”

int main(){
	const int a = 1;
	int & b = const_cast<int&>(a);
	b = 2;
	cout << a ;
	cout << b;
}

虽然上面程序运行没有问题,但定义const常量的初衷肯定就是为了不修改,所以出现了上述情况肯定是程序设计有问题。
在这里插入图片描述
而且你会发现调试窗口中,两个变量的值按照我们所想,但打印时,却是先打印1,后打印2。这是因为常量折叠。

常量折叠

将上面代码进行反汇编。

	const int a = 1;
00971F72 C7 45 F4 01 00 00 00 mov         dword ptr [a],1  
	int & b = const_cast<int&>(a);
00971F79 8D 45 F4             lea         eax,[a]     //可以发现,引用本质是指针,这里把a的地址先存到eax
00971F7C 89 45 E8             mov         dword ptr [b],eax   //再把地址赋值给b
	b = 2;
00971F7F 8B 45 E8             mov         eax,dword ptr [b]  //先把地址给eax
00971F82 C7 00 02 00 00 00    mov         dword ptr [eax],2    //中括号里面放的是地址
	cout << a ;
00971F88 8B F4                mov         esi,esp  
00971F8A 6A 01                push        1      //打印的时候,直接入栈的是1,这里发生了常量折叠
00971F8C 8B 0D D4 D0 97 00    mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (097D0D4h)]  
00971F92 FF 15 E4 D0 97 00    call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (097D0E4h)]  
00971F98 3B F4                cmp         esi,esp  
00971F9A E8 0E F3 FF FF       call        __RTC_CheckEsp (09712ADh)  
	cout << b;
00971F9F 8B F4                mov         esi,esp  
00971FA1 8B 45 E8             mov         eax,dword ptr [b]  
00971FA4 8B 08                mov         ecx,dword ptr [eax]  
00971FA6 51                   push        ecx  
00971FA7 8B 0D D4 D0 97 00    mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (097D0D4h)]  
00971FAD FF 15 E4 D0 97 00    call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (097D0E4h)]  
00971FB3 3B F4                cmp         esi,esp  
00971FB5 E8 F3 F2 FF FF       call        __RTC_CheckEsp (09712ADh) 

常量折叠就是,在编译阶段,对该变量进行值替换。类似宏定义。

使用指针时的未定义行为

int main(){
	const int a = 1;
	int * b = const_cast<int*>(&a);
	*b = 2;
	cout << &a <<endl;
	cout << b << endl;
	cout << a << endl;
	cout << *b << endl;
}

在这里插入图片描述

使用const_cast去掉const限定符

只有当对象原本就是非常量时,才是正确的行为。

void func(const int& a)//形参为,引用指向const int
{
	int& b = const_cast<int&>(a);//去掉const限定,因为原本为非常量
	b++;
	return;
}

int main()
{
	int a = 100;
	func(a);
	cout << a << endl;  // 打印101
	return 0;
}

此函数的形参本来设置为int& a就好,但这里只是为了体现用法。

使用const_cast添加const限定符

const string& shorter(const string& s1, const string& s2) {
	return s1.size() <= s2.size() ? s1 : s2;
}

string& shorter(string& s1, string& s2) {
	//重载调用到上一个函数,它已经写好了比较的逻辑
	auto &r = shorter(const_cast<const string&>(s1), const_cast<const string&>(s2));
	//auto等号右边为引用,类型会忽略掉引用
	return const_cast<string&>(r);
}

const string&版本函数为比较字符串长度的正确实现,因为比较长度时不会改变字符串,所以参数和返回值都为const。
当实参为const时,由于函数重载,会调用到const string&版本函数,这也是期望的结果。

但当实参为非const时,我们希望还是继续调用已经写好比较逻辑的const string&版本函数,但返回值希望返回string &,所以这里再封装一层函数。(这里一个知识点,函数重载是忽略返回值,且忽略形参的顶层const,可以这么理解,有顶层const的概念,说明参数是引用或指针,但我们主要关心的是指向的数据,所以要忽略顶层const)(因为参数忽略顶层const,所以重载时只关心底层const是否一样)

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
该错误通常出现在尝试在一个const类型的ros消息指针上调用getMessage()函数时。由于该指针是const的,因此不能对其进行修改,而getMessage()函数是用于修改消息的非const函数,因此编译器会报错。 解决这个问题的方法是,使用boost::const_pointer_cast函数将const类型的指针转换为非const类型指针。具体步骤如下: 1. 在你的C++代码中包含以下头文件: ``` #include <ros/ros.h> #include <ros/console.h> #include <rosgraph_msgs/Log.h> #include <boost/shared_ptr.hpp> #include <boost/const_pointer_cast.hpp> ``` 2. 然后,创建一个ros::Subscriber对象来订阅rosout节点: ``` ros::Subscriber sub = nh.subscribe("/rosout", 1000, &callback); ``` 其中,"/rosout"是要订阅的rosout节点的话题名称,1000是消息队列的大小,callback是当接收到消息时要调用的回调函数。 3. 在回调函数中,将const类型的指针转换为非const类型指针,然后再使用getMessage()函数: ``` void callback(const boost::shared_ptr<const rosgraph_msgs::Log>& msg) { boost::shared_ptr<rosgraph_msgs::Log> nonconst_msg = boost::const_pointer_cast<rosgraph_msgs::Log>(msg); std::string message = nonconst_msg->getMessage(); ROS_INFO_STREAM("Message: " << message); } ``` 这样,你就可以在C++代码中使用getMessage()函数获取订阅的消息了。注意,使用const_pointer_cast函数进行类型转换时要非常小心,避免意外修改const指针所指向的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值