前端老铁别再瞎改state了!Immutable.js让你数据稳如老狗(附避坑指

前端老铁别再瞎改state了!Immutable.js让你数据稳如老狗(附避坑指

前端老铁别再瞎改state了!Immutable.js让你数据稳如老狗(附避坑指

前端老铁别再瞎改state了!Immutable.js让你数据稳如老狗(附避坑指南)

说实话,我刚开始写React那会儿,真是被state这玩意儿折腾得够呛。你懂的,就是那种明明代码看着没问题,界面死活不更新,或者更诡异的是——数据明明改了,但日志打印出来跟没改一样。后来我才慢慢悟了,这哪是React的锅啊,分明是咱JavaScript里那个"引用赋值"在搞事情。

为啥你总在React里搞出莫名其妙的bug?

这事儿得从JavaScript的基本功说起。咱们平时写代码,对象和数组都是引用类型,啥意思呢?就是说当你写 const newState = oldState 的时候,你以为newState是个全新的对象,实际上它就是个指针,跟oldState指着同一块内存呢。

来,看个真实的翻车现场:

// 你以为的安全操作,实际上是个大坑consthandleUpdate=()=>{const newState = state;// 兄弟,这只是个引用啊! newState.user.name ='张三';// 你以为是改newState,实际上state也被改了setState(newState);// React一看:引用没变?那我不更新};

看到没?React的setState(或者useState的setter)判断要不要重新渲染,默认就是浅比较。你传给它的newState和state在内存里是同一个地址,React直接判定"没变化",页面当然不更新。更坑的是,有时候你确实触发了更新,但因为其他地方也引用了这个对象,那些地方的数据也跟着变了——这就是传说中的"副作用",debug的时候能让你怀疑人生。

还有一种更隐蔽的情况,就是在Redux里。你reducer里要是直接改state,Redux-devtools都检测不到变化,时间旅行调试直接失效。我就见过有同事在reducer里写 state.list.push(newItem),然后回来问我为啥Redux不工作…兄弟,你这是在mutation的边缘疯狂试探啊。

Mutable数据结构到底有多坑?

咱再多说几句这个mutable的坑。在复杂应用里,数据往往是嵌套的,比如用户信息里套着订单列表,订单里又套着商品详情。这种时候你要是想复制一份数据来改,用展开运算符都费劲:

// 这代码看着就累,层级深了直接写哭const newState ={...state,user:{...state.user,profile:{...state.user.profile,address:{...state.user.profile.address,city:'北京'// 我就想改个城市,写了这么多层...}}}};

这还只是个四层嵌套,要是遇到表格数据、树形结构,这代码能写出颈椎病来。而且手写的展开运算符特别容易漏层级,漏了就又变成浅拷贝,bug找上门只是时间问题。

还有个性能问题。你想啊,每次都要深拷贝整个对象树,数据量大的时候那不得卡死?而且React的shouldComponentUpdate或者React.memo,它怎么判断数据变没变?如果每次都要深度遍历比较,那性能直接爆炸。所以immutable的思路就很有诱惑力了——如果数据不可变,那比较两个数据是否相等就简单了,直接 oldData === newData,O(1)复杂度,美滋滋。

Immutable.js真能救你于水火?

说实话,我第一次听说Immutable.js的时候,内心是抗拒的。又要学个新库?又要搞一堆新API?我原生JS还没玩明白呢。但真被mutable数据坑了几次之后,我还是屈服了。用了一段时间之后,真香。

它解决的核心问题就是:让你能像操作普通对象数组那样操作数据,但底层保证每次操作都返回全新的数据结构,而且共享未修改的部分(结构共享),性能还不差。这就好比给你一辆车,开着跟普通车一样,但自带防弹功能,还不用你额外操心。

Immutable.js是个啥玩意儿

别被名字吓到,它其实就是个"数据防篡改工具箱"。你想啊,immutable翻译成"不可变",听起来挺高大上的,实际上就是个规矩:数据一旦创建就不能改,要改就创建新的。这跟咱们平时写代码的习惯确实反着来,但用习惯了之后,你会发现思维都变清晰了。

核心思想:每次改数据都给你整个新的,旧的纹丝不动

Immutable.js底层用的是一种叫"持久化数据结构"(Persistent Data Structure)的东西,配上"结构共享"(Structural Sharing)的优化。啥意思呢?就是说当你修改一个Map或者List的时候,它不会把整个数据结构复制一遍,而是只复制修改的那条路径上的节点,其他的都共享。

画个图你就明白了(虽然我没图,但你想象一下):假设你有个大树形结构,改一个叶子节点,Immutable.js只会重新创建从根到那个叶子的路径上的节点,其他的分支还是指向原来的内存地址。这样既保证了不可变性,又不会浪费内存和性能。

跟原生JS对象、数组说拜拜,换上Map、List这些新面孔

这是Immutable.js最让人不习惯的地方。你不能直接 obj.key = value 这样赋值了,也不能 arr.push(item) 这样添加元素。你得用 map.set('key', value)list.push(item),而且这些方法都返回新的实例,原来的不动。

刚开始确实烦,感觉写个代码啰里啰嗦的。但习惯了之后,你会发现这种"显式"的操作方式反而让数据流更清晰。而且Immutable.js提供的API比原生JS丰富多了,很多复杂操作一行代码就搞定,后面我会详细说。

手把手带你玩转Immutable.js

好了,废话不多说,咱们直接上手。先从最基础的安装开始,然后一个个API过,保证你看完就能拿去用。

从安装到基本API:Map、List、Set怎么用才不翻车

安装很简单,npm或者yarn都行:

npminstall immutable # 或者yarnadd immutable 

然后引入,建议这样写:

import{ Map, List, Set, fromJS, toJS }from'immutable';

Map:对象的专业替代品

Map就是用来替代普通对象的,但功能强大多了:

// 创建一个Map,可以传普通对象,也可以传数组const user =Map({name:'李四',age:25,hobbies:List(['coding','gaming'])// 嵌套List也没问题});// 获取值,用get,支持链式调用 console.log(user.get('name'));// '李四' console.log(user.getIn(['hobbies',0]));// 'coding',获取嵌套值// 设置值,返回新的Map,原Map不变const newUser = user.set('age',26); console.log(user.get('age'));// 还是25 console.log(newUser.get('age'));// 26// 批量设置,用mergeconst updatedUser = user.merge({age:26,city:'上海'});// 删除值const userWithoutAge = user.delete('age');// 判断是否存在某个key console.log(user.has('name'));// true// 获取所有keys或values console.log(user.keySeq().toArray());// ['name', 'age', 'hobbies'] console.log(user.valueSeq().toArray());// ['李四', 25, List]

看到没?API设计得很直观,就是方法名跟原生JS有些区别,适应几天就好了。

List:数组的升级版

List替代数组,但 immutable 版本的:

// 创建List,可以传数组const numbers =List([1,2,3,4,5]);// 添加元素,push返回新List,原List不变const moreNumbers = numbers.push(6); console.log(numbers.size);// 5,原List还是5个 console.log(moreNumbers.size);// 6// 在头部添加,用unshiftconst prefixed = numbers.unshift(0);// 插入到指定位置const inserted = numbers.insert(2,99);// 在索引2处插入99// 删除,用delete(注意不是splice)const removed = numbers.delete(2);// 删除索引2的元素// 切片,跟数组的slice一样const sliced = numbers.slice(1,3);// [2, 3]// 查找索引const index = numbers.indexOf(3);// 2// 包含判断const hasThree = numbers.includes(3);// true// 排序、反转、过滤、映射,都有,而且都返回新Listconst doubled = numbers.map(n=> n *2);const evens = numbers.filter(n=> n %2===0);const sorted =List([3,1,4,1,5]).sort();

Set:去重神器

Set就是集合,自动去重:

const set1 =Set([1,2,3,3,3]); console.log(set1.toArray());// [1, 2, 3],重复的3被去掉了// 并集、交集、差集,数学课代表狂喜const set2 =Set([2,3,4]);const union = set1.union(set2);// Set [1, 2, 3, 4]const intersect = set1.intersect(set2);// Set [2, 3]const subtract = set1.subtract(set2);// Set [1]

嵌套数据更新?别慌,updateIn和setIn来救场

这是Immutable.js最实用的功能之一。前面说了,深拷贝嵌套对象很麻烦,但在Immutable.js里,一行代码搞定:

// 假设有个复杂的嵌套结构const data =fromJS({company:{departments:[{name:'技术部',employees:[{name:'王五',level:'P5'},{name:'赵六',level:'P6'}]}]}});// 场景:把技术部第一个员工的level改成P6// 原生JS写法要疯,Immutable.js这样写:const newData = data.setIn(['company','departments',0,'employees',0,'level'],'P6');// 更复杂的场景:给这个员工涨薪,基于当前薪资计算const newData2 = data.updateIn(['company','departments',0,'employees',0,'salary'],(salary =10000)=> salary *1.2// 涨20%,如果salary不存在默认10000);// 在数组中间插入元素?用updateIn配合updateconst newData3 = data.updateIn(['company','departments',0,'employees'],employees=> employees.insert(1,Map({name:'新来的',level:'P4'})));

看到 setInupdateIn 的威力了吧?路径用数组表示,想多深就多深。setIn 是直接设置值,updateIn 是拿到当前值,经过你的函数处理后再设置,适合那种基于旧值计算新值的场景。

还有个 getIn 用来取值,前面示例里用过了,这三个方法配合起来,处理嵌套数据简直不要太爽。

深度比较变简单了?是的,===就能判断内容是否一样

这是immutable数据最爽的地方之一。因为每次修改都返回新实例,所以比较两个数据是否相等,直接用 === 就行了,不需要深度遍历:

const map1 =Map({a:1,b:2});const map2 = map1.set('b',2);// 设置相同的值const map3 = map1.set('b',3);// 设置不同的值 console.log(map1 === map2);// true!因为值没变,Immutable.js会返回原实例 console.log(map1 === map3);// false,值变了,返回新实例// 这在React优化里太好用了const MyComponent = React.memo(({ data })=>{// 如果data是Immutable对象,直接比较引用就行 console.log('渲染了');return<div>{data.get('name')}</div>;});// 父组件里const[user, setUser]=useState(Map({name:'张三',age:20}));consthandleClick=()=>{setUser(user.set('age',20));// 设置相同的值};// 点多少次按钮,MyComponent都不会重新渲染,因为user引用没变

这个特性在shouldComponentUpdate或者React.memo里简直是神器,性能优化零成本。

toJS()和fromJS()这俩双胞胎,什么时候用哪个?

这俩方法是你跟普通JavaScript世界打交道的桥梁,必须搞清楚。

fromJS:JS对象 → Immutable对象

当你从后端拿到JSON数据,或者要处理现有的普通对象时,用它:

// 后端返回的数据const apiResponse ={users:[{id:1,name:'张三'},{id:2,name:'李四'}],total:100};// 转成Immutableconst immutableData =fromJS(apiResponse);// 现在你可以用Immutable的各种方法了const firstUser = immutableData.getIn(['users',0]);const newData = immutableData.set('total',101);

注意,fromJS 是深度转换,会把所有嵌套的对象和数组都转成Map和List。如果你只想转一层,用 Map(apiResponse)List(apiResponse)

toJS:Immutable对象 → 普通JS对象

当你要把数据传给不支持Immutable的库(比如一些图表库、表单库),或者要提交给后端时,用它:

// 假设你处理完数据,要传给一个普通的JS库const immutableConfig =Map({width:100,height:200,colors:List(['red','blue'])});// 转回去const plainConfig = immutableConfig.toJS(); console.log(plainConfig);// { width: 100, height: 200, colors: ['red', 'blue'] }// 在React组件里渲染时,如果你用了Immutable存state,记得取值的时候转一下// 或者在render里转,或者提前转好存起来constUserList=({ users })=>{// users是Immutable Listreturn(<ul>{users.toJS().map(user=>(<li key={user.id}>{user.name}</li>))}</ul>);};

重要警告toJS() 每次调用都会返回一个全新的普通对象,即使Immutable数据没变。这意味着如果你在React组件里直接在render里调用 toJS(),会导致每次渲染都是新的引用,优化全白费。所以要么在useMemo里转,要么在数据进入组件前就转好。

Immutable.js香在哪,又臭在哪

用了这么久,咱们客观评价一下,不吹不黑。

优点拉满:性能优化有门道、状态追踪不再玄学、避免意外副作用

性能优化真的香

前面说了,immutable数据用 === 比较就行,这让React的性能优化变得简单。在Redux里,selector用reselect写起来也更高效,因为比较成本极低。而且Immutable.js的结构共享机制,让大数据量的更新也不会卡,它不会真的复制整个对象树。

状态追踪清清楚楚

因为数据不可变,每次变化都是新对象,你在Redux DevTools里看时间旅行,或者在console里打印日志,不会遇到那种"我明明打印了,怎么值变了"的诡异情况。数据流向变得特别清晰,从哪来,到哪去,中间经过哪些变换,一目了然。

副作用?不存在的

函数式编程的核心优势,纯函数好测试、好推理。你的reducer、你的数据处理函数,输入确定输出就确定,不用担心哪个角落偷偷改了全局状态。团队开发的时候,这点尤其重要,能减少很多"谁改了我的数据"的撕逼。

缺点也扎心:学习曲线有点陡、调试时控制台看懵了、bundle体积悄悄涨

学习成本确实存在

团队里来了新人,得先培训一波Immutable.js的API,不能上来就写。而且API跟原生JS有差异,经常有人写着写着就 obj.key = value 了,然后问为啥不更新。还有就是跟TypeScript配合的时候,类型定义要写对,不然一堆红线看着头疼。

调试体验确实拉胯

你在控制台 console.log 一个Immutable对象,看到的是 Map { "key": "value" } 这种,或者更糟的是 t.Map{},展开看结构也不直观。解决方案是装个浏览器插件(Immutable.js Object Formatter),或者在打印前 .toJS(),但总归是麻烦。

// 这样看很难受 console.log(immutableMap);// Map { size: 2, _root:... }// 这样看舒服多了,但别忘了生产环境别这么干 console.log(immutableMap.toJS());// { name: '张三', age: 20 }// 或者用这个技巧,只在开发环境转constlog=(label, immutableData)=>{if(process.env.NODE_ENV==='development'){ console.log(label, immutableData.toJS());}};

包体积确实大了点

Immutable.js压缩后还有几十KB,对于追求极致首屏速度的项目,可能得掂量掂量。不过现在都有tree shaking,按需引入能小不少。或者你可以考虑用immer,那个更轻量,但Immutable.js的功能确实更强大。

跟React/Vue配合起来爽不爽?Redux用户狂喜,但Vue党可能觉得多此一举

React + Redux:绝配

这是Immutable.js最经典的战场。Redux要求reducer纯函数、不可变数据,Immutable.js完美契合。而且React的优化机制(shouldComponentUpdate、React.memo)配合Immutable的引用比较,简直是天作之合。很多大型React项目(比如Facebook自己的一些产品)都用这套组合拳。

Vue:可能没必要

Vue的响应式系统本身就是基于数据劫持的,它追踪的是数据的变化,而不是引用。你在Vue里直接改对象属性,Vue能检测到的。所以Vue官方也不推荐用Immutable.js,觉得多此一举。当然,如果你跟React项目共享代码,或者就是喜欢immutable的编程风格,也可以用,但确实不是必须的。

MobX:看情况

MobX也是响应式的,跟Vue类似,但MobX也支持observable的map和array。用不用Immutable.js看团队喜好,但MobX本身的数据结构已经是响应式的了,再加一层Immutable可能有点冗余。

真实项目里怎么用才不翻车

理论说了一堆,咱们来点实战的。我在几个项目里用过Immutable.js,总结了一些经验。

状态管理场景:Redux + Immutable.js 经典组合拳

这是最常见的用法。整个Redux的state树都用Immutable对象存,reducer里全部用Immutable的API操作:

// store.jsimport{ createStore }from'redux';import{ Map, fromJS }from'immutable';import rootReducer from'./reducers';const initialState =fromJS({user:null,posts:[],ui:{loading:false,error:null}});const store =createStore(rootReducer, initialState);// reducers/user.jsimport{ Map }from'immutable';const initialUserState =Map({profile:null,preferences:Map({theme:'light',language:'zh-CN'})});exportdefaultfunctionuserReducer(state = initialUserState, action){switch(action.type){case'SET_USER_PROFILE':return state.set('profile',Map(action.payload));case'UPDATE_PREFERENCE':// 更新嵌套属性,用setInreturn state.setIn(['preferences', action.key], action.value);case'RESET_USER':return initialUserState;default:return state;}}// selectors.js - 配合reselect使用import{ createSelector }from'reselect';constgetUserState=state=> state.get('user');constgetPostsState=state=> state.get('posts');exportconst getUserProfile =createSelector([getUserState],userState=> userState.get('profile'));exportconst getUserTheme =createSelector([getUserState],userState=> userState.getIn(['preferences','theme']));// 在组件里使用import{ useSelector }from'react-redux';constUserProfile=()=>{// 用selector取值,已经是immutable对象了const profile =useSelector(getUserProfile);// 渲染的时候要转JS,或者直接用getreturn(<div><h1>{profile?.get('name')}</h1><p>{profile?.get('email')}</p></div>);};

这套组合用了好几年,稳得很。就是写selector的时候要注意,返回的最好是primitive值(string、number这种),这样在组件里用的时候更方便。

表单处理、表格编辑这类高频更新场景实测效果

表单数据通常结构复杂,而且更新频繁,用Immutable.js管理很合适:

// 一个复杂的表单状态const[formData, setFormData]=useState(fromJS({basicInfo:{name:'',email:'',phone:''},address:{province:'',city:'',detail:''},items:[]// 动态添加的表单项}));// 处理嵌套字段变化consthandleBasicChange=(field, value)=>{setFormData(prev=> prev.setIn(['basicInfo', field], value));};// 处理动态数组constaddItem=()=>{setFormData(prev=> prev.updateIn(['items'],items=> items.push(Map({name:'',quantity:1,price:0}))));};constupdateItem=(index, field, value)=>{setFormData(prev=> prev.setIn(['items', index, field], value));};constremoveItem=(index)=>{setFormData(prev=> prev.updateIn(['items'],items=> items.delete(index)));};// 提交前验证并转JSconsthandleSubmit=()=>{const plainData = formData.toJS();// 验证逻辑... api.submitForm(plainData);};

表格编辑也是类似,特别是那种可以行内编辑、拖拽排序的表格,Immutable.js的API让数据处理变得简单很多。比如拖拽排序,用 insertdelete 组合一下就行,不用自己写一堆splice逻辑。

别一上来就全量替换,先从局部复杂状态试试水

如果你是个Immutable.js新手,别一上来就把整个项目的state都换成Immutable。建议先从那些让你头疼的复杂状态开始,比如:

  • 深层嵌套的配置对象
  • 需要频繁CRUD的列表数据
  • 多组件共享的、容易出副作用的状态

局部试用没问题了,再考虑全面替换。这样风险小,团队也有时间适应。

遇到问题别砸键盘,排查思路在这

用Immutable.js这些年,我也踩过不少坑,总结一些常见问题。

为啥组件不更新?八成是你忘了toJS或者shouldComponentUpdate写错了

最常见的情况:

// 错误示范1:在组件里直接比较immutable对象constMyComponent=({ data })=>{useEffect(()=>{ console.log('data变了');},[data]);// 如果data是immutable对象,这样比较的是引用,可能有问题};// 错误示范2:shouldComponentUpdate里直接比较classMyComponentextendsReact.Component{shouldComponentUpdate(nextProps){returnthis.props.data !== nextProps.data;// 如果data是plain object,这比较的是引用}}// 正确做法:确保比较的是immutable对象,或者转成primitive值constMyComponent=({ data })=>{// 如果data是immutable,直接用const name = data.get('name');useEffect(()=>{ console.log('name变了');},[name]);// 依赖primitive值};

还有一种情况是,你在父组件里把immutable对象转成了JS对象传给子组件,但转的时候没用useMemo,导致每次渲染都是新对象,子组件优化失效:

// 错误:每次渲染都生成新对象constParent=()=>{const data =useSelector(state=> state.get('data'));return<Child data={data.toJS()}/>;// 每次toJS都返回新对象};// 正确:缓存转换结果constParent=()=>{const data =useSelector(state=> state.get('data'));const plainData =useMemo(()=> data.toJS(),[data]);return<Child data={plainData}/>;};

内存爆了?小心无限嵌套或忘记转换回普通对象

Immutable.js本身有结构共享,内存管理挺好的,但如果你搞出循环引用,或者无限嵌套的数据结构,那也会炸。还有就是,如果你把immutable对象存到了全局变量、localStorage,或者传给了Web Worker,记得先 toJS(),不然序列化的时候会出问题。

控制台打印全是t.Map{}?装个浏览器插件或者console.log前.toJS()一下

前面说过了,这是调试体验问题。建议团队统一装Chrome插件"Immutable.js Object Formatter",然后在代码规范里约定:开发环境的console.log统一用包装函数,自动转JS。

老司机私藏技巧大放送

最后分享一些我积累的技巧,让你用得更爽。

用Record定义结构化数据,比Map更安全还带默认值

Record是Map的"严格版",你定义好结构后,不能随意添加新字段,还有默认值:

import{ Record }from'immutable';// 定义一个User结构const User =Record({id:null,name:'',email:'',age:0,isActive:true});// 创建实例const user1 =newUser({name:'张三',email:'[email protected]'}); console.log(user1.get('name'));// '张三' console.log(user1.get('age'));// 0,默认值// 不能随意加字段,会忽略或者报错(取决于严格模式)const user2 =newUser({name:'李四',unknownField:'test'}); console.log(user2.get('unknownField'));// undefined// 设置值,返回新的Recordconst user3 = user1.set('age',25);// 可以用get方法直接访问属性(需要配置)// 或者用destructuring,但要先toJS

Record的好处是类型安全,团队协作的时候,防止有人手滑写错字段名。配合TypeScript用更爽。

结合immer?别混着用!除非你想给自己加难度

immer是另一个实现immutable的库,语法更贴近原生JS(用proxy实现),体积也更小。但我不建议在一个项目里混用Immutable.js和immer,除非你在做渐进式迁移。两个库的API风格完全不同,团队维护成本翻倍。选一个,坚持到底。

TypeScript怎么配?类型提示搞对了开发效率翻倍

Immutable.js有官方的类型定义,但用起来有点啰嗦:

import{ Map, List, fromJS }from'immutable';// 定义类型interfaceUser{ name:string; age:number;}// Map的类型要这样写const userMap: Map<string,any>=Map({ name:'张三', age:20});// 更好的方式是用泛型(如果确定结构)const userMap2 =Map<string,string|number>({ name:'张三', age:20});// 从JS对象转的时候,类型推断可能失效,需要手动指定const data =fromJS({ users:[]})as Map<string, List<any>>;// 或者定义整个state的类型interfaceAppState{ user: Map<string,any>; posts: List<Map<string,any>>;}const initialState: AppState ={ user:Map(), posts:List()};

TypeScript配置好了,IDE提示很爽,但前期写类型定义确实费时间。建议用Record代替Map,类型定义会更清晰。

懒加载+按需引入,别让Immutable.js拖慢首屏速度

如果你只用了Immutable.js的一小部分功能,可以按需引入:

// 别这样,全引入了import Immutable from'immutable';// 这样,只引入需要的import{ Map, List }from'immutable';// 或者更狠的,用babel-plugin-lodash那种思路,只引入具体方法// 不过Immutable.js的tree shaking支持还行,按需引入模块就够了

对于不是首屏必须的逻辑,可以用React.lazy或者动态import,把Immutable.js的代码分割出去:

// 假设这个组件用了很重的Immutable操作const HeavyDataProcessor = React.lazy(()=>import('./HeavyDataProcessor'));// 在需要的地方<Suspense fallback={<Loading />}><HeavyDataProcessor /></Suspense>

好了,差不多就这些。Immutable.js这玩意儿,刚开始用确实觉得麻烦,但习惯了之后,你会发现数据管理变得特别踏实。特别是大型项目,团队人多的时候,immutable的数据流能避免很多低级错误。当然,小项目或者Vue项目,可能确实没必要上这么重的方案,immer或者干脆手写深拷贝可能更合适。

反正工具就是工具,没有银弹,只有适不适合。希望这篇能让你少踩几个坑,写代码的时候心里更有底。有啥问题,咱们评论区(哦不对,咱们私下)再聊。

在这里插入图片描述

Read more

C++ ⾼性能内存池

C++ ⾼性能内存池

目录 项⽬介绍 小知识点补充  定位new 英语单词: 什么是内存池 1.池化技术 2.内存池 3.内存池主要解决的问题 3.1 效率问题 3.2 碎片化  3.2.1 外碎片  4.了解一下malloc 先设计⼀个定⻓的内存池 New的实现 Delete的实现 性能测试 脱离malloc直接在堆中 ObjectPool.h Test.cpp ⾼并发内存池整体框架设计 ⾼并发内存池--thread cache 申请内存: 释放内存: 计算对象大小的对齐映射规则 Common.h ThreadCache.h 解决thread cache的锁问题 编辑 ⾼并发内存池--central

By Ne0inhk
C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象:封装特性的实现与实战应用 💡 学习目标:掌握类与对象的核心概念,理解封装的本质与价值,能够独立设计并实现具有封装特性的 C++ 类。 💡 学习重点:类的定义与对象实例化、访问权限控制、构造函数与析构函数的使用、封装的实战场景应用。 一、类与对象的核心概念 ✅ 结论:类是 C++ 面向对象编程的核心载体,是对一类事物属性和行为的抽象描述;对象是类的具体实例,是内存中实际存在的实体。 1.1 类的组成 一个完整的 C++ 类通常包含两部分: * 成员变量:描述类的属性,如人的姓名、年龄,圆的半径等。 * 成员函数:描述类的行为,如人的吃饭、跑步,圆的面积计算等。 1.2 类的定义格式 #include<iostream>#include<string>

By Ne0inhk
C++性能优化:提升代码执行效率的艺术

C++性能优化:提升代码执行效率的艺术

C++性能优化:提升代码执行效率的艺术 一、学习目标与重点 本章将深入探讨C++性能优化的核心知识,帮助你掌握提升代码执行效率的艺术。通过学习,你将能够: 1. 理解性能优化的基本概念,掌握性能分析的方法 2. 学会优化内存管理,减少内存泄漏和内存碎片 3. 理解CPU优化技巧,提高代码的执行速度 4. 学会优化I/O操作,提升文件和网络读写的效率 5. 培养性能优化思维,设计高效的代码 二、性能优化的基本概念 2.1 性能优化的原则 性能优化应该遵循以下原则: * 先测量后优化:在优化之前,必须先测量代码的性能,找出瓶颈所在 * 优化瓶颈:只优化对性能影响最大的部分 * 保持代码的可维护性:优化后的代码应该易于理解和维护 * 测试优化结果:优化后必须测试代码的正确性和性能提升效果 2.2 性能分析工具 常用的性能分析工具包括: * GProf:GNU的性能分析工具 * Valgrind:内存调试和性能分析工具

By Ne0inhk

C++模拟器开发实践

1、非修改序列算法 这些算法不会改变它们所操作的容器中的元素。 1.1 find 和 find_if * find(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。 * find_if(begin, end, predicate):查找第一个满足谓词的元素。 * find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出现的位置。 vector<int> nums = {1, 3, 5, 7, 9}; // 查找值为5的元素 auto it = find(nums.begin(

By Ne0inhk