关于C++里const的pitfall
文章主要对MICHAEL PENG(以下称MP)对某开源代码的评价而写。 作者希望给技术讨 论增加一点深度。
MP认为只要“语义const“就必须加上, 比如他的评论
class IRule {
public:
// MichaelPeng: Name函数可以设置为const
virtual const char* Name(void) = 0;
...
};
上面是个抽象类(abstract class), 定义了继承类必须实现的方法。我把微软专用 的LPCSTR 改成了对应的const char*, 相信大家都看得懂。
这个函数返回一个“内 容不可修改“的指针, 我这里打上了引号, 根据下面会讲到。
MP认为, 这个函数应该定义为
virtual const char* Name(void) const = 0;
这个我是很同意的。 但是MP在理论时是不是没有看到潜在的问题呢? 假如我已经写了上百个继承类了, 然后我需要要写一个复杂的。我需要去到另一服 务器去拿这个NAME。 为了程序的性能, 我只能在第一次调用的时候去拿
class myRemoteRule : public IRule
{
public:
myRemoteRule(const char* serverA);
virtual const char* Name(void) const;
private:
std::string strName;
std::string serverAddr;
};
const char* myRemoteRule::Name(void) const
{
if (strName.empty()) {
strName = getNameFromRemote(serverAddr);
}
return strName.c_str();
}
然后编译, 结果编译器给了错误。 因为上面的语句里成员strName 被修改了, 函 数不能为CONST。
我已经写了几百个类了, 我得一个一个改回去。 我去翻翻C++的书, 果然有如何 FQ的技术:
const char* myRemoteRule::Name(void) const
{
if (strName.empty()) {
const_cast<myRemoteRule*>(this)->strName = getNameFromRemote("rule-server" );
}
return strName.c_str();
}
这只是一个小CASE。 实际正常的CLASS都有很多数据成员和函数成员。 如果需要翻 很多墙, 整个CODE 都会充满了const_cast. 实际情况有可能是很复杂的, 看了一个函数的定义就说它一定是const是把世界看 得太简单了。 另外, 说const就能优化也是一种理解错误。 C++书上说const 常数可以直接替代, 以及常数字符串可以优化, const 函数并不能优化。 实际上由于const_cast的存 在, 编译器必须把const指针当成non const, 因为无法预知这是否会修改。 比如:
const char* name = rule.Name();
... 100 lines later
const_cast<char*>(name)[0] = 'P';
这段CODE完全合法。
转载于:https://www.cnblogs.com/CplusplusExpert/archive/2010/12/02/1894887.html
关于C++里const的pitfall相关推荐
- iOS 里const在修饰对象时候的用法
玩iOS的小伙伴对const应该很不陌生, 在声明全局常量的时候很多时候都会用到, 但是有时候修饰对象很迷惑下面是个人总结, 下面的地址都是模拟的 1. const NSString *str1 = ...
- 《认清C++语言》---谈谈const
const类型修饰符可以: 1) 用来说明符号常量和常数组(必须同时进行初始化,以后不能再更新) C++中,用关键字const修饰的标识符称为符号常量,或称为const变量. 常量在使用前必须先定义 ...
- 浅谈const int *,int const *与int *const
最近恰好在学习浙江大学翁恺老师的<C语言程序设计>,老师对指针与const的见解颇深,感兴趣可在mooc搜索视频观看9.1-5节 在开始之前,先介绍一条const的规则:const默认与其 ...
- 《程序员的自我修养》第3章---目标文件里有什么
第3章 目标文件里有什么 3.1 目标文件的格式: 编译器编译源代码后生成的文件叫做 "目标文件". 目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程, ...
- react 返回一个页面_Fiber 内部: 深入理解 React 的新 reconciliation 算法
最近在看 React, 发现一篇深度好文, 忍不住就翻译了. React 是一个用于构建用户界面的库, 它的核心是跟踪组件状态变化并将它们更新到页面上. 在 React 中, 我们称这个过程为 rec ...
- 进击webpack4 (优化篇)
进击webpack 4 (基础篇一) 进击webpack4 (基础篇二:配置 一) 进击webpack4 (基础篇三:配置 二) 不解析不依赖第三方模块的模块 noParse 有一些第三方模块,它本身 ...
- jset编写测试vue代码_详解使用jest对vue项目进行单元测试
最近领导对前端提出了新的要求,要进行单元测试.之前使用vue做了一个快报名小程序的pc端页面,既然要做单元测试,就准备用这个项目了,之前有些react的经验,vue还是第一遭 vue-cli3.0单元 ...
- React服务端渲染实现(基于Dva)
React服务端渲染实现 (基于Dva) 功能 基于 Dva 的 SSR 解决方案 (react-router-v4, redux, redux-saga) 支持 Dynamic Import (不再 ...
- H5 六边形消除游戏开发
试玩地址,目前只适配pc端.源码 六边形游戏的鼻祖应该是这个 hex-frvr,原作者开发用的是 pixi 游戏引擎,本着快速开发的理念,本游戏采用 cocos creator,UI 延用 hex-f ...
最新文章
- redis分布式缓存(三)
- 关于 hibernate 官网的例子 出现的问题
- 利用java实现excel转pdf文件
- sqlserver 插入数据时异常,仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'XXXXX.dbo.XXXXXXXXX'中的标识列指定显式值。...
- 手机发送验证码的业务逻辑探究-主要是安全性,响应性
- wait notify的错误理解
- jenkins安装部署全过程(linux)
- Flash 与数学:圆的切线(2)
- Hyperworks——Optistruct学习分享
- 机器人工程师学习计划
- matlab解全微分方程,通过MATLAB求二阶全微分方程解析解
- 计算机话筒技术指标,麦克风
- matlab关于图像切割的一些总结:imcrop,getrect,ndgrid,函数
- iatf16949内审员_IATF16949:2016内审员试题及答案.pdf
- 阿里巴巴国际站如何查看优秀同行产品关键词方法?
- 【Android容器组件—LinearLayout】
- 国内智能硬件和物联网行业研发人员的城市分布图
- 食饵捕食者模matlab,食饵——捕食者数学模型研究.doc
- diagnosing error in object detectors 浅析
- android自定义截图,Android实现截屏功能
热门文章
- linux文件重定向 dup,linux之dup和dup2函数解析
- 【安全知识分享】工程项目夏季、雨季、夜间、防汛施工安全培训教育(附下载)
- c++调用opencv实现图片叠加以及添加水印效果
- Oracle 11g中文繁体特殊乱码问题解决
- c语言中begin用法,C++ set cbegin() 使用方法及示例
- python下载迅雷资源助手_python练习七—P2P下载
- pathon中的元组与序列
- 华硕的电脑装linux系统安装教程,华硕笔记本电脑一键重装系统详细教程
- 高德百度地图如何获取附近小区酒店银行等?
- signature=ac75cb7977a45c0f7d8a73dca59a4c27,合肥2016年8月24日至2016年9月5日交通违章查询...