自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(163)
  • 收藏
  • 关注

原创 iOS 架构:MVC 与 MVVM

MVC(Model-View-Controller)是 iOS 开发中最基础、最经典的架构模式。它将程序严格划分为三个角色:Model(模型)负责管理数据和核心业务逻辑;View(视图)负责界面的渲染和用户交互反馈;Controller(控制器)则作为协调者,负责连接 Model 和 View。在标准的数据流中,View 与 Model 之间是严格隔离的。当用户触发操作时,View 通过 Target-Action、Delegate 或 DataSource 机制将事件传递给 Controller;

2026-08-18 21:53:07 211

原创 OC三大基石——Runtime、RunLoop 和 KVO

RunLoop 的完整工作流程是一个不断循环的过程:首先通知 Observer 即将处理事件,接着检查并处理到来的 Timer 和 Source 事件;Runtime 是一套用 C 和汇编编写的底层 API 库,它将 Objective-C 从编译期的静态绑定彻底解放为运行期的动态调度。KVO(Key-Value Observing)是一种无侵入式的观察者模式,允许一个对象监听另一个对象特定属性的变化。,当属性变化时,系统会向已释放的观察者发送消息,导致野指针崩溃(EXC_BAD_ACCESS)。

2026-08-18 21:51:12 267

原创 ios的声明式框架--swiftui

状态(State)就是驱动界面变化的源数据,当状态改变时,UI 会自动更新。SwiftUI 提供了一套属性包装器(Property Wrappers)来管理不同场景下的状态。SwiftUI 通过链式调用修饰符来改变视图的外观和行为。需要注意的是,修饰符是。SwiftUI 的视图组合就像搭乐高积木,通过组合基础视图来构建复杂的界面。的,每次调用都会返回一个新的视图实例。当你的状态是一个复杂的类(遵循。谁使用别人创建的数据,谁用。协议)时,这两个极易混淆。在 SwiftUI 中,

2026-08-18 21:44:03 181

原创 iOS 新手村通关指南:彻底搞懂 UIKit 四大核心基石

UIKit 是苹果提供的一个核心框架(Framework)。它为你提供了构建 iOS 应用界面和处理用户交互所需的所有基础设施。

2026-08-18 21:37:20 317

原创 iOS 动画:core Animation 底层原理

图元组装 -> 光栅化 -> 帧缓冲区(Frame Buffer) -> 屏幕。当遇到无法在当前帧缓冲区直接合成的特效时,GPU 必须开辟一块新的临时内存缓冲区(Off-Screen Buffer),把特效画完后,再作为纹理贴回主帧缓冲区。这涉及昂贵的上下文切换(Context Switch)和内存拷贝。

2026-08-18 21:29:38 353

原创 Swift 并发编程指南

在 iOS 和 macOS 开发中,并发编程是提升应用性能、保持 UI 流畅的核心技术。随着 Swift 5.5 的发布,苹果引入了基于的现代并发模型,彻底改变了我们编写异步代码的方式。本文将带你全面梳理 Swift 并发体系,从传统的 GCD、OperationQueue,到现代的Task和Actor,帮助你构建安全、高效的并发应用。

2026-08-18 21:20:36 347

原创 刷力扣用for求了无数次数组和?别急,numeric来救急

旨在让标准库算法(如sortreducefor_each)能够利用多核 CPU 加速运行。执行策略 (Execution Policy):你告诉算法“可以怎么跑”(串行、并行、还是向量化)。并行 (Parallel):算法实际利用多个线程同时工作的状态。归约 (Reduction):一种将一堆数据“压缩”成一个结果的计算模式(如求和、求最大值),它是并行计算中最常见的操作。在 C++17 之前,标准算法(如std::sort)只能是单线程顺序执行的。C++17 允许你在调用算法时传入一个执行策略对象。

2026-03-26 15:04:26 399

原创 tx面试官:随机数你直接用c++库的就行,我:平常没用过,只会c的随机数种子,面试官:我们今天就到这

前几天在面tx的时候要求我做算法题,关于随机性的,但是脑子一抽突然随机数不会生成了(c的都不记得了),才发现cxx有很多学习时不常用但很关键的库,今天我们来看看C++11的 <random>

2026-03-26 14:18:08 73

原创 git常用命令小总结

注:配置name和email不需要你在gitee有账号,可以是任何name和email(也不需要网络)只是用于标记这条commit是谁发的,如果你输入了gitee配置的账号,那么在你push时就会出现绿格子.(同时,如果你有gitee的情况下,可以在gitee上手动创建仓库,然后把仓库的链接复制到服务器进行clone,git init的仓库是不会绑定到gitee上的)一定要注册gitee账号?工作区就是你还没有用git时写的代码,暂存区就是git add后的地方,版本库就是git commit的本地仓库。

2026-03-15 18:53:06 403

原创 C++面试题:atomic你知道吗,其中的内存序你了解吗?

他只保证了当前这行代码是原子的,但不保证其上下代码的顺序性,也就说即使是在这行代码上面写的也可能在之后执行这个demo读取的data有可能是0也有可能是42,因为可能会编译期和运行期重排导致运行顺序不同(多线程下)2.memory_order_acquired和memory_order_releaseacquired的作用是,保证acquired这条读操作语句之后的操作,绝对不会重排到其之前执行release的作用是,保证release这条写操作语句之前的操作,绝对不会重排到其之后执行。

2026-03-09 14:56:32 416

原创 面试题:无锁编程的weak和strong

在C++的atomic中,有两个是用于更新原子变量值的函数compare_exchange_weak和compare_exchange_strong,我们来看一下他的工作原理面试题:对于这两个函数的区别在哪里,内部如何保证交换成功,什么情况下会用哪个?d我们首先定义一个原子变量std::atomic<bool> b (false);他的函数是把expeced的值更新为new_val,其中这个expected是b.load()得到的,但赋值过程不一定这么顺利.

2026-03-09 13:33:55 239

原创 C++11——tuple(pair加强版)

std::tuple 是C++11引⼊的⼀个模板类,它允许将多个不同类型的值组合成⼀个单⼀的对象。tuple(元组)是⼀个固定大小的异构值集合,可以包含不同类型的元素。它是 std::pair 的加强版本, pair 只能保存两个元素,tuple可以存任意数量的元素。至于如何访问某一元素,在pair中我们有first,second,tuple中提供了get函数。除此之外,我们可以利用std::tie对tuple进行解包(把tuple中的元素都拿出来存储)cout<<std::get<0>(t1);

2026-01-25 18:29:06 73

原创 C++11--using、enum class、static_assert

C++11中新增了using可以替代typedef,using的别名语法覆盖了typedef的全部功能,不少场景还更清晰⼀些,⽐如函数指针的重定义,其次最⼤的变化是⽀持带模板参数重定义的语法。是C++元编程和模板编程中⾮常有⽤的⼯具,它可以帮助开发者在编译期捕获错误,提⾼代码的健壮性。注意它和assert的区别,sa(简称)是编译时检查,assert是运行时,如果有错误,sa会报编译错误,而assert会终止程序允许,此外,sa必须是编译时常量表达式(constexpr),assert任何表达式都可以。

2026-01-25 17:53:30 93

原创 C++11的类型推导——auto

auto不能⾃动推导出引⽤类型,所以我们如果想将auto推导为引⽤类型,需要明确的写:auto &x=i(i是引用);ri1是ci的引用,而ri1推导时类型是引用对象的类型(上面的引用规则,和ri1、ri2前面的const没关系了,因为是引用推导)因此ri1是顶层const(ci的),而auto推导r4又会忽略顶层const,ci因此r4类型为int。⾸先使⽤引⽤其实是使⽤引⽤的对象,特别是当引⽤被⽤作初始值时,真正参与初始化的其实是引⽤对象的值,所以编译器推导auto为引⽤对象的类型,⽽不是引⽤。

2026-01-25 17:26:38 570

原创 C++20的consteval和constinit(接C++11的constexpr)

而consteval的出现,如果其修饰了函数,即代表这个函数一定是编译时计算的函数,不能当成普通函数使用,否则无法通过编译,解决了函数的不确定性(写法就是在函数前的constexpr换成consteval即可)C++11提出的constexpr修饰函数时我们知道,其即可以当成编译时的函数(写法严格按照要求),当不满足constexpr条件时也可以当成普通函数使用。constexpr 和 constinit 都可以修饰变量,它们的核⼼区别在于"初始化时机"和"可变性"。

2026-01-20 21:00:47 93

原创 C++11——constexpr常量表达式及演进

上半部分解释了什么是常量表达式,下半部分解释了constexpr关键字如何使用,简单来说就是,没有指针的情况下,使用constexpr表示常量表达式(编译器会优化),有*下,使用关键字修饰的是=左边,即代表=左边的变量已经定死了,这就是为什么p1会报错,因为p1是指针的指向内容无法修改,但指向可以修改。另外constexpr成员函数不能是虚函数。通俗地讲,const修饰的内容,以及指针指向的内容无法修改,但指针指向可以修改的是底层const,无法修改指针指向,但指针指向的内容可以修改的是顶层const。

2026-01-20 20:46:22 684

原创 Redis分布式——分布式锁

当加锁期间,如果其他服务器想买票,就会尝试设置key-value,肯定是设置失败的,至于是直接返回还是阻塞等待要根据实际设定。引入多个redis主节点,加锁时,按一定顺序把每一个节点都尝试加锁,当加锁成功数量超过总节点数一半视为加锁成功,可以有效解决一台redis节点挂了另一个衔接不上锁的问题,解锁同理,按顺序解锁。解决方案:引入校验机制,给服务器编号,每个服务器有自己的身份标识,在加锁时,key-value中的key代表根据哪个资源加锁(比如某一车次),value标识锁是哪个服务器加的(服务器编号)

2026-01-20 17:17:20 721

原创 Redis——事务

并不是连上服务器就有队列,当我们开启事务的时候才有,此时我们在客户端输入命令,其不会立即执行,而是放入队列中,当遇到执行事务时,会把队列的任务按顺序全部执行(主线程执行,执行后处理别的客户端)redis同样也是把多个操作打包,要么全都执行要么不执行,但其不保证执行的正确性,也不支持回滚操作,而mysql的原子性是执行正确,若出错可以回滚,因此是否有原子性存在争议。当执行watch key时,给key一个版本号(数字),每次修改时,版本号会变大。因此,一致性也不保证:因为其不保证操作的正确性,也不可以回滚。

2026-01-16 22:21:28 426

原创 Redis——认识持久化、RDB、AOF

什么是持久化?也就是数据持久化,当系统重启后仍能恢复保存的数据特性。这个特性在mysql中最有体现,因为其把数据都保存在磁盘中,其实,redis也具有持久化的特性,虽然其把数据都保存在内存中(一旦重启,内存中的数据都将清除),但其有自己的持久化策略,在向内存存数据时,同时也像磁盘中存,当重启时,就会从磁盘中获取数据到内存(为什么不向mysql一样直接与磁盘交互?虽然听着确实是麻烦,但因其自有的策略使得整体还是比mysql快的,两边的写是不同策略,理论上两边数据相同,但持久化导致数据不一定一致)

2026-01-16 17:27:10 539

原创 一篇搞定C++连接Redis客户端使用教程

我们简单写一段测试代码,需要包含刚才安装的库redis++(已经被我们拷贝到了/usr/local/include/sw下)我们连接redis服务器,都是通过创建对象来简介使用命令,相关api在最上面的github网站上都有介绍。首先需要安装hiredis(rpp是基于hiredis实现的,是一个c语言实现的redis客户端)编译需要包含两个redis静态库和线程库,运行可执行文件就会输出PONG,即成功了。到这里我们的环境安装就ok了,接下来我们连接redis服务器。安装后就会得到以下文件。

2026-01-15 21:34:41 105

原创 Redis数据库命令和客户端介绍

Redis中的database是现有的,我们不能创建和删除提供的数据库,默认给我们提供16个数据库0-15,我们默认操作的是0号,各数据库之间隔离,互不影响,如果我们要切换到其他数据库使用命令 select num。在mysql中,我们有create database的概念,而一个database中可以有多个表,那么在Redis 中,是否存在database这样的概念?在实际开发中,我们这种通过命令行交互redis的方式是很少用的,大多数是用redis 的api,通过使用api来操作redis服务器。

2026-01-14 21:49:55 93

原创 Redis的value类型介绍——zset

3.zcount key min max 返回权重在范围[min,max] 的元素个数,如果想排除边界可以写成(min,(max,还有一个类似命令,zrangebyscore,根据分数找元素。zset是有序的set集合,这个有序和list不一样,这个zset通常是升序/降序,排列的规则是赋予元素中的权重,比如分数。5.zpopmax key [count] 删除分数最高的元素(count个)(如果分数相同会根据member字典序排序)xx:只更新元素的权重 nx只添加没有的元素,不做更新。

2026-01-13 16:18:14 117

原创 Redis的value类型介绍——set

5.smove source destination member 把member从source删除并插入destination(两个set)set类型是集合,集合一个最大的特点就是无序性,不像list,即使元素相同但顺序不同仍然是两个list,并且,集合中的元素不能重复!sinterstore dest key1 [key2...]把这若个个set的交集放在dest的set中。4.srandmember key:随机获取set中的元素(不会删除)向set中插入元素(已有的元素无法继续插入)

2026-01-12 20:49:47 74

原创 Redis的value类型介绍——list

如果list内有元素,则blpop brpop和lpop rpop没区别,但list若为空,b系列的pop就会进入阻塞状态,直到list有元素插入再执行pop操作。list里面的数据是”有序“的有序并非是升序或降序,而是保持相对的顺序,list的元素是允许重复的,hash的field则不允许。value类型是list的时,其对应的是deque(内部编码方式并非简单的组,而是接近deque)命令中如果设置多个键,会左->右遍历键,一旦有一个对应的list可弹出,立即执行并返回。

2026-01-12 20:06:21 322

原创 Redis的value类型及编码方式介绍——hash

如果hash元素比较少就会用ziplist表示,为了节省空间,如果元素多了,读写效率会显著降低,此时会用hashtable表示。虽然我们说过string也可以作为缓存,但存储一些结构性的数据,比如用户信息,hash更合适(string的Json也可以)Redis中的hash,并不是key——value的那一套机制,而是这个key对应的value本身是hash结构。在key对应的hash中在键为field的值设置为value(可以一次性设置多个)返回设置成功的对数。获取hash key中的所有value。

2026-01-12 17:51:30 104

原创 Redis的value类型及编码方式介绍——string

在指定key后再加上value字符串(前提key对应的value是string类型)如果key不存在,此命令等同于set。如果value类型是string,那么我们存入的时候是什么,编码的时候就是什么,不会进行任何转换(已二进制方式存储),其不仅可以存文本数据,还包括整数,json,xml等。XX:key存在,则更新key对应的value(以及对应的过期时间),key不存在不作为(返回nil)如果没写此选项:key不存在,创建新键值对,key存在,覆盖原有的value(数据结构可能改变)

2026-01-12 17:25:36 596

原创 Redis——value的数据类型与单线程工作模型

Redis内部实际上是单线程工作模型(主要其处理的任务逻辑都是简单和快速的,不是很吃CPU)但并不是真正的内部只有一个线程在工作,在多个Redis客户端连接时,会有多个线程处理网络中的IO,只有到了Redis服务器端才会单线程执行,因此不会造成线程安全问题,一旦到了服务器就是串行。然而Redis在实际编码中,并没有完全的把上面的数据结构直接拿过来用,其为了提升效率节省curd时间,真正的结构并不一定和上述结构相同,但其保证对外的功能是不变的。3.单线程模型,避免了线程竞争的开销(加锁解锁)

2026-01-12 15:15:59 145

原创 Redis——基本通用命令

需要注意的是,我们要知道Redis也是一种客户端——服务器的模式,多个客户端可以同时连接服务器,可以存放数据,其他客户端可以通过服务器拿到数据并使用。以上是Redis的通用命令,也就是说无论value是什么类型都可以使用的命令(实际通用命令还有非常多,这里只是介绍了几个常用的)需要注意的的,key必须是字符串,当然你输入数字也可以最后都会以字符串的形式存储,返回的也是字符串,而且存字符串时不用加"",给指定的key值设定时间(key必须存在),经过了second秒后key值自动删除,成功返回1失败返回0。

2026-01-12 14:06:37 175

原创 Redis初识——Redis的基本特性

Redis是把数据在内存上存储,但内存的数据”易失“一旦进程退出/重启数据容易丢失,因此Redis还会再存一份到硬盘(辅)如果Redis重启,就会加载存放在硬盘的那份备用数据。Redis存储数据量是有限的,一旦数据量过大,我们会引入多个主机进行存储,部署多个Redis节点,每个节点存储一部分。Redis是通过键值对来存储数据,key都是string,value可以是上面的数据结构,称为非关系型数据库。针对Redis,我们可以直接进行简单交互式命令来操作,也可以通过一些脚本来批量执行操作,并可带有一些逻辑。

2026-01-11 15:56:50 169

原创 Redis初识——什么是Redis

常被用作数据库、缓存和消息中间件,用内存存储数据?还真是,但Redis的作用不体现在这方面,我们直到,进程具有独立性,进程之间的内存数据是不共享的,如果想共享就需要做到——进程间通信,目前最常用的就是利用网络进行通信,这时Redis就会发挥作用了,其在分布式系统中体现巨大的优越性。但Redis和MySQL比最大的劣势是存储空间比较小~,对于高性能可以用Redis,但不是要求极致且存储数据大还得是MySQL。一起用呗,就是我们耳熟能详的缓存,经常使用的数据放在Redis,剩下的给MySQL存储。

2026-01-11 15:23:29 254

原创 C++ 11 atomic 原子性操作

是模板类,支持大部分基础数据类型(boolcharintlong、指针等),也支持用户自定义的 “可平凡复制” 类型(Trivially Copyable,即能通过 memcpy 复制的类型,如不含指针的结构体)。cpp// 1. 基础类型原子变量// 原子布尔(标志位)// 原子整型(计数器)// 原子长整型// 原子指针// 2. 自定义平凡类型(需 C++20 或编译器支持,部分编译器 C++11 即可)int x;int y;

2025-11-23 21:26:04 1344

原创 C++11 std::mutex 互斥锁

多个线程互相持有对方需要的锁,且都不释放,导致所有线程永久阻塞(程序卡死)。避免方法所有线程都按相同的顺序加锁(如先锁mtx1,再锁mtx2。。),避免交叉等待。

2025-11-23 18:44:33 460

原创 C++ 11 thread库与this_thread(线程)

C++11的线程库std::thread,线程,是进程的执行分支,一个进程中可包含多个线程,可以指定执行流完成不同的任务,我们主要介绍C++中线程库的线程用法。我们需要创建线程入口,比如用函数、lambda、仿函数、成员函数作为入口,参数直接跟在调用对象后,下图是我们最简单的函数入口,直接在后面传参即可。detach():用于分离线程,子线程后台运行,与主线程无关了,等子线程结束后资源自动回收(分离后无法调用join)此外,下面两个join()是使主线程阻塞,等t1和t2执行完毕后再回收信息结束运行。

2025-11-23 17:22:24 225

原创 查缺补漏c语言——c标准字符串函数

把str2的字符串拷贝到str1去,返回str1的指针,覆盖str1原有的所有,需要足够空间拷贝。若str1>str2 返回值>0 小于则返回 <0 相等return 0。在str1中找到首次出现str2的位置,如果未找到返回NULL。拼接函数str2接到str1的后面(str1后要留够空间)字符串比较函数,从首字符开始逐个进行ascii码值的比较。(a<b<c<d....)并不是谁长谁大!返回str字符串的长度,不算\0。

2025-11-19 20:53:04 234

原创 查缺补漏c语言——静态修饰与类型转换

普通的局部变量创建后是放在。

2025-11-19 00:57:59 287

原创 查缺补漏C语言——与“#”的爱恨情仇

_DATE__ __FILE__ __LINE__ (分别表示当前日期,文件名和对应行号)可以把其当成常量的宏进行输出。

2025-11-18 22:58:02 173

原创 背包问题——完全背包

在此问题中,我们可以推广,比如我们腾出至少两个v[i]的体积,那么在选第i个的情况下就是取max(dp[i-1][j-v[i]]+w[i],dp[i-1][j-2*v[i]]+2*w[i],.......推广到n个)我们用这个就可以推导出方程。我们的状态表示dp[i][j]表示在前i个物品中,不超过j体积下所有方案的最大价值(一种物品的个数不再是只有一个而是无限个)在01背包问题的情况下,我们是dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])

2025-11-16 21:43:13 487

原创 动态规划算法经典问题——01背包问题

初始化方面,第一行除了第一个位置我们为0剩下都是-1,因为我选第0个物品的情况下(即不选)我是无法把你的背包装满的,但是第一个位置背包体积为0,某种意义上也满足要求,但价值是0.如果选第i个,除了考虑是否v[i]<=j,还要满足dp[i-1][j-v[i]]不等于-1(即满足要求恰好装满)这时候背包恰好剩下v[i]个位置直接放入即可。当选时,首先要判断第i个物品体积是否大于j,如果大于了,只选第i个都已经过大了,显然不满足要求,因此我们要加个判断条件,在此条件下,它就等于。(对于问题1的状态表示)

2025-11-16 17:17:24 534

原创 零基础带你实现Json--Rpc框架项目(主题发布与订阅实现)

本篇我们要实现其功能是服务的注册与发现。在之前实现的Rpc请求与响应功能中,我们很明显的可以看到其是一对一的关系,这就意味着一旦服务端出现问题后,客户端就无法获得服务了。因此,我们应该采用分布式,多个服务端进行服务注册功能,每一个服务端告诉我们的注册中心自己的ip以及能提供的服务,服务的调用方,首先进行一次服务发现,知道哪些主机可以提供哪些服务。

2025-11-15 16:05:18 939

原创 零基础带你实现Json—Rpc框架项目(Rpc功能实现)

除此之外,我们还需要定义一些项目中需要用到的字段消息正文消息类型Rpc请求&响应 主题操作请求&响应 服务操作请求&响应响应码定义RPC请求类型定义主题的操作类型服务的操作类型。

2025-11-11 23:36:18 1045

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除