当前位置: 首页 > article >正文

再论观点“C++是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)”

再论观点“C是否应避免使用普通指针而使用智能指针包括shareduniqueweak”PS笔者这次投稿的问题是https://www.zhihu.com/question/319277442。老规矩顺手投稿的问题必须先回答问题本身。笔者粗浅的看了一下下面的回答咱们抛开卖课的卖书的不谈看了下专门直接回答“c是否应避免使用普通指针而使用智能指针”这个问题的回答。我跟一些答主一样是不赞同智能指针是裸指针的代替品这个说辞的。很显然智能指针根本不是裸指针的上位替代——它俩解决的是完全不同的问题。std::unique_ptrT 表达的是独占所有权人话就是我占着这玩意了你们谁也别抢走std::shared_ptrT 表达的是共享所有权这个玩意对于所有的访问者都是共享占据的而裸指针 T* 虽然是一个从语言诞生之初就有的东西可以表达的是的是我不拥有这个对象我只是用一下或者看看它。这三件事压根不在一个层面上。笔者强调的是“可以表达的是”因为真的没有任何约束。。。有人说为什么呢把所有的 T* 换成 std::shared_ptrT 不就万事大吉了说的就是几年前我自己信了智能指针要无脑取代裸指针。我们不妨想想这么做的后果——首先你给每一个原本只是借用关系的对象都加上了引用计数的开销哪怕它根本不需要共享所有权。每一次拷贝都是一次原子操作每一次析构都要走一遍控制块的判断逻辑。更要命的是一旦你用 shared_ptr 把整个项目串起来循环引用几乎是迟早的事——两个对象互相持有对方的 shared_ptr谁都别想析构。然后你就开始到处补 weak_ptr代码变成了一锅粥。说到底笔者认为写C不去仔细想清楚资源所属的关系也就是资源的所属权乱用智能指针和乱用裸指针都是不符合工程规范的很有可能出问题的但是你能这么写自由的翻车这一块C Core Guidelines 资源管理章节的核心思路说得很明白用智能指针管理资源用裸指针或非拥有包装类型处理其他所有情况。换句话说智能指针是所有权的工具不是万能指针替代品。所以笔者鲜明的亮出来自己的观点不是因为裸指针不安全了咱们无脑上智能指针反而丢弃了结合工程场景实事求是分析选择的能力来选择正确的抽象反过来就不说了因为回答本身站在这一侧。我要做的是另外寻求这样的思路——裸指针的不安全一部分原因是语义缺失。鬼知道你的T*到底是我能借用我能持久化存储他挂掉了有人会不会告诉我防止我一个油门踩上去访问结果直接炸车了我们完全可以在梳理清楚自己的资源图到底关系如何的场景下如果表达的是我一个人的确占据这个资源的时候老实用std::unique_ptr。几个人大概率之后更多人要一起共享的占据整个资源那就用std::shared_ptr特别的发现这几个人的关系出现了循环引用那就使用std::weak_ptr破除循环引用的问题防止资源down不掉的情况。那就剩下最后一个问题了你声称裸指针语义的模糊造成了不安全那好咋解决呢我的一个想法是不是消灭裸指针而是让裸指针的语义变得可读。BorrowedT 告诉你这是非空借用ObserverPtrT 告诉你这是可空观察——它们本质上都是裸指针的语义标注说白了就是用一些语法和几个字母当文档告诉你哥啊别乱用咱们这里的裸指针这个意思而不是所有权管理工具。真正的所有权管理是 unique_ptr 和 shared_ptr 的事而真正的弱引用安全是 weak_ptr 的事。核心概念四层语义模型我很好奇不知道有没有人有过这样的经历拿到一个项目按照需要打开一个函数看到参数列表里赫然写着T* ptr然后就开始犯嘀咕——这个指针到底是拥有这个对象呢还是只是借用一下调用者是不是需要检查 nullptr函数返回后这个对象还活着吗裸指针T*什么都可能是也什么都没承诺。它可能是拥有者比如new出来还没交给智能指针的那个瞬间可能是借用者传给函数用一下也可能是一个悬垂指针对象早就没了指针还留着。编译器不会帮你区分注释也不一定靠得住没准注释是AI写的代C Core Guidelines 里有一条 R.3 说得很直白裸指针非ownerT的T*应该只用来表示非拥有的观察或借用。但在实际代码里我们拿到一个T*根本分不清它到底想表达什么语义。所以我们今天要做的事情很明确梳理 C 中不拥有对象的各种指针表达方式然后手搓两个语义明确的类型——BorrowedT和ObserverPtrT——让代码自己说话。先把结论放在前面非拥有不等于安全可空不等于能判活这些类型各有各的适用场景用错了比用裸指针还坑。在动手写代码之前我们需要先理清一件事——C 里的不拥有到底有几种语义。这里我们把它分成四层第一层借用Borrowing。T*和T是最原始的借用方式。你拿到一个指针或引用用完就还回去不管理对象的生命周期也不关心对象什么时候销毁。适合函数参数这种短暂同步使用的场景但千万别存下来以后再用。毕竟资源没有义务告诉你咱们这资源炸了请您另寻高就。第二层显式观察Observation。从这里开始我们就出现了更语义化的说明。我的意思是——当我们持有ObserverPtrT的适合我们不过是想说——他虽然被持久化了但是我们丝毫不拥有它甚至我们没办法知道他是否失效。“我只是观察它我知道有这个事情。但是我不拥有它或者说他到底能不能用我一点保证不了”。和裸指针的区别在于可读性听着有点鸡肋了哈哈看到ObserverPtrT就知道这是一个纯观察关系。但它和T*一样不能判活——对象销毁了你还拿着 ObserverPtr解引用就是 UB。第三层非 owning 弱引用Weak Reference。这是WeakPtrT登场的层次。它和 ObserverPtr 的核心区别是对象销毁后你可以安全地检测到失效。为此它需要一个独立于对象的 control block 来记录对象是否还活着。但是你说。我还想lock一下把他延长生命周期额做不到。第四层shared ownership 弱引用。这就是std::weak_ptrT它和第三层的区别在于它依赖std::shared_ptrT的控制块调用lock()会临时延长对象生命周期。现在我们用一个表格来对比这四层特性T*TBorrowedTObserverPtrTWeakPtrTstd::weak_ptrT可空是否否设计上是是是拥有对象否否否否否否延长生命周期否否否否否lock() 临时延长对象销毁后安全判空否否否否是是适合函数参数是是推荐可以过重过重适合类成员可以但不明确可以不推荐推荐推荐推荐适合异步回调危险危险危险危险是是⚠️ 注意看这一行——“对象销毁后安全判空”。前四种类型T*、T、Borrowed、ObserverPtr全部做不到。只有真正拥有独立 control block 的 WeakPtr 才行。控制块有效的独立的表达了我们这个东西是否有效基于此Chrome家的WeakPtr说你只能知道我活着没weak_ptr再吊一点可以直接lock从观察一跃成为资源的访问者之一也就是基于访问者增多的生命周期延长BorrowedT让借用语义显式化BorrowedT想解决的问题很简单函数参数里出现const T或者T*的时候调用者和阅读者无法一眼看出这只是一个借用。我们需要一个类型来把非空、非拥有、短期使用这个语义钉死在类型系统里。C Core Guidelines 里的gsl::not_nullT做了类似的事情——它约束指针不能为空但不表达借用语义。我们的BorrowedT在此基础上更进一步它是非空的它是非拥有的而且它禁止从临时对象构造——因为你不能借用一个马上就销毁的东西。先看核心实现// borrowed.h// 教学版 BorrowedT显式非空借用语义// 注意这不是生产级实现用于教学演示#pragmaonce#includetype_traits#includeutilitytemplatetypenameTclassBorrowed{public:// 从左值引用构造——这是最正常的用法explicitBorrowed(Tref)noexcept:ptr_(ref){}// 禁止从临时对象构造Borrowed(T)delete;// 禁止从 nullptr 构造T* 重载只接受非空指针Borrowed(std::nullptr_t)delete;// 从裸指针构造但调用者需保证非空explicitBorrowed(T*ptr)noexcept:ptr_(ptr){assert(ptr!nullptrBorrowedT requires a non-null pointer);}// 默认拷贝和移动——借用是可以传递的Borrowed(constBorrowed)default;Borrowedoperator(constBorrowed)default;Borrowed(Borrowed)default;Borrowedoperator(Borrowed)default;// 访问接口Tget()constnoexcept{return*ptr_;}T*operator-()constnoexcept{returnptr_;}Toperator*()constnoexcept{return*ptr_;}private:T*ptr_;};// 辅助函数从引用创建 Borrowed省去写 explicit 构造templatetypenameTBorrowedTborrow(Tref)noexcept{returnBorrowedT(ref);}那很显然我们会有这些问题为什么禁止从临时对象构造这是BorrowedT和裸引用之间最关键的区别。看这个场景std::stringget_name();// 如果允许从临时对象构造就会出这种事// Borrowedstd::string b(get_name()); // 临时对象在表达式结束时销毁// 到这里get_name返回的对象就被销毁掉了这个时候访问持有的引用就是踩到地雷了// b.get(); // 悬垂引用T被标记为 delete之后编译器会在编译期直接拒绝这种用法。这是 Rust 借用检查器在 C 里能做的最接近的模拟——虽然不像 Rust 那样全面但至少堵住了最常见的坑。为什么构造函数是 explicit防止隐式转换。你不会希望某个函数接受BorrowedFoo然后被隐式地从Foo调用——借用的动作应该是有意识的。为什么有borrow()辅助函数纯粹是为了方便。因为构造函数是 explicit 的每次写BorrowedFoo(foo)有点啰嗦borrow(foo)更清爽。标准库也有类似的设计比如std::make_pair、std::make_shared。为什么不禁止作为类成员技术上可以做到比如通过static_assert加 SFINAE但实际上过度工程化了。我们在文档和惯例中约定Borrowed 不应该作为类成员保存就足够了。编译器强制和团队规范之间我们选择后者——因为 C 的类型系统本来就不擅长表达生命周期约束要不然为什么我们在这里坐下来谈这个用蹩脚的方式来表达我们的意思呢硬做反而容易引入不必要的复杂度。一个典型的正确用法voidprocess_data(Borrowedconststd::vectorintdata){// 调用者保证 data 非空我们直接用for(constautoitem:data.get()){// ...}}intmain(){std::vectorintv{1,2,3};process_data(borrow(v));// 清晰我在借用 v}和直接用const std::vectorint相比Borrowed版本的优势不在运行时行为它们生成的代码几乎一样而在于可读性——函数签名直接告诉你这是一个借用。ObserverPtrT可空的非拥有观察如果说BorrowedT是给函数参数用的那ObserverPtrT就是给类成员用的。它的语义是我观察这个对象但我不拥有它我也不负责它的生命周期。事实上C 标准委员会曾经提出过一个非常类似的类型std::experimental::observer_ptrW收录在 Library Fundamentals TS v2 中。它的定义是A non-owning pointer, or observer. The observer stores a pointer to a second object, known as the watched object. An observer_ptr may also have no watched object.遗憾的是截至 C26似乎是26我没翻到新消息如果我又搞错了欢迎喷我observer_ptr仍未被正式纳入标准仍停留在 TS 阶段。但它设计得非常清晰值得参考。我们的教学版会在其基础上做简化// observer_ptr.h// 教学版 ObserverPtrT可空非拥有观察指针// 参考了 std::experimental::observer_ptr (Library Fundamentals TS v2)#pragmaonce#includecstddeftemplatetypenameTclassObserverPtr{public:// 默认构造空观察ObserverPtr()noexcept:ptr_(nullptr){}// 从 nullptr 构造空观察ObserverPtr(std::nullptr_t)noexcept:ptr_(nullptr){}// 从裸指针构造开始观察explicitObserverPtr(T*ptr)noexcept:ptr_(ptr){}// 拷贝和移动ObserverPtr(constObserverPtr)default;ObserverPtroperator(constObserverPtr)default;ObserverPtr(ObserverPtr)default;ObserverPtroperator(ObserverPtr)default;// 重新绑定观察对象voidreset(T*ptrnullptr)noexcept{ptr_ptr;}// 释放观察关系返回原指针T*release()noexcept{T*oldptr_;ptr_nullptr;returnold;}// 访问T*get()constnoexcept{returnptr_;}Toperator*()constnoexcept{return*ptr_;}T*operator-()constnoexcept{returnptr_;}// 检查是否有观察对象explicitoperatorbool()constnoexcept{returnptr_!nullptr;}// 交换voidswap(ObserverPtrother)noexcept{T*tmpptr_;ptr_other.ptr_;other.ptr_tmp;}private:T*ptr_;};// 相等比较templatetypenameT,typenameUbooloperator(constObserverPtrTa,constObserverPtrUb)noexcept{returna.get()b.get();}templatetypenameTbooloperator(constObserverPtrTa,std::nullptr_t)noexcept{return!a;}// 辅助函数templatetypenameTObserverPtrTmake_observer(T*ptr)noexcept{returnObserverPtrT(ptr);}ObserverPtr 和 Borrowed 有什么区别核心区别在两个字上可空。Borrowed 表达的是我保证非空的借用ObserverPtr 表达的是我可能为空的观察。前者适合函数参数调用者保证非空后者适合作为持久化的类成员或者存储成员观察对象可能还没设置或者被设置成空。为什么 ObserverPtr 不是 WeakPtr这是最常见的误解。ObserverPtr 和 WeakPtr 的区别不在于 API 长什么样它们都有get()、operator-、operator bool()而在于对象销毁后会发生什么。ObserverPtr 内部就是一个裸指针对象销毁了它什么都不知道解引用就是 UB。真正的 WeakPtr 需要一个独立于对象的 control block 来记录存活状态——这是后面笔者计划投稿到其他问题和专栏的文章了典型的正确用法——类成员观察关系classLogger;classService{public:voidset_logger(Logger*log){logger_.reset(log);}voiddo_work(){if(logger_){// 有 Logger 才记录没有就算了// ...}}private:ObserverPtrLoggerlogger_;// 我观察 Logger但不拥有它};典型的错误用法——异步回调// 错误ObserverPtr 不能保证对象还活着voidService::async_task(){// 如果 Service 在回调执行前被销毁logger_ 就是悬垂的// 这个 callback 捕获了 logger_执行时可能 UBautocallback[this](){if(logger_){// 孩子们这种东西很危险// logger_ 的 ptr_ 指向的 Logger 可能已经不存在了// operator bool 只检查 ptr_ 是否为 nullptr// 如果 Logger 被销毁但 ptr_ 没被 reset这里就是 UB}};// post_callback(callback); // 别这么做}Borrowed、ObserverPtr 和裸指针的关系现在我们回头看把这三个类型和裸指针的关系说清楚。BorrowedT本质上是T的一个类型安全的包装。它比T多了禁止从临时对象构造的约束比T*多了非空的保证。它的开销等于零——编译器优化后和裸引用完全一样。它的限制也和裸引用一样不能判活。ObserverPtrT本质上是T*的一个语义标注。它和裸指针的运行时行为完全一致区别只在于可读性——当你看到一个ObserverPtrLogger类型的成员变量时你不需要猜测它是不是拥有那个 Logger类型名字已经替你回答了。但同样的它不能判活。而裸指针T*的问题不在于它不安全而在于它不表态——拿到一个T*你不知道它是拥有的还是非拥有的是可空的还是保证非空的是短期的还是长期的。Borrowed和ObserverPtr解决的是这个不表态的问题。叽里呱啦说了一大堆Summarize一下不是因为裸指针不安全了咱们无脑上智能指针反而丢弃了结合工程场景实事求是分析选择的能力来选择正确的抽象我们完全可以在梳理清楚自己的资源图到底关系如何的场景下如果表达的是我一个人的确占据这个资源的时候老实用std::unique_ptr。几个人大概率之后更多人要一起共享的占据整个资源那就用std::shared_ptr特别的发现这几个人的关系出现了循环引用那就使用std::weak_ptr破除循环引用的问题防止资源down不掉的情况。T*和T是 C 最原始的借用机制本身不表达所有权语义BorrowedT表达非空借用适合函数参数禁止从临时对象构造不延长生命周期ObserverPtrT表达可空非拥有观察适合类成员不提供判活能力非拥有不等于安全——Borrowed 和 ObserverPtr 都不能在对象销毁后安全检测失效它们的核心价值是语义表达不是运行时安全——让代码自己说话减少歧义如果还要油门踩上去那没辙。参考资源C Core Guidelines - R.3: A raw pointer (a T*) is non-owningstd::experimental::observer_ptr - cppreferenceGSL: Guidelines Support Library (Microsoft) —gsl::not_null和gsl::spanC Core Guidelines - F.7: For general use, take T* or T arguments rather than smart pointers

相关文章:

再论观点“C++是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)”

再论观点“C是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)” PS:笔者这次投稿的问题是:https://www.zhihu.com/question/319277442。老规矩,顺手投稿的问题&…...

KMS_VL_ALL_AIO:开源智能激活工具让Windows和Office激活变得简单

KMS_VL_ALL_AIO:开源智能激活工具让Windows和Office激活变得简单 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统未激活的水印烦恼吗?Office软件频繁弹…...

告别抢票焦虑:DamaiHelper大麦网自动化抢票工具完整指南

告别抢票焦虑:DamaiHelper大麦网自动化抢票工具完整指南 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 你是否经历过这样的时刻?心心念念的演唱会门票开售,你…...

机器学习项目开发模式解析:从提交历史看规模、协作与演化规律

1. 项目概述:从代码提交中解码机器学习项目的真实工作流在机器学习项目的日常开发中,我们每天都在与Git打交道,提交代码、更新模型、调整参数。但你是否想过,这些看似随意的提交背后,是否隐藏着某种规律?一…...

magic - trace:高分辨率追踪利器,解决应用难题,还能深入洞悉程序运行!

magic - trace 概述magic - trace 能够收集并展示进程活动的高分辨率追踪信息,可用于解决生产环境中应用程序处理请求速度慢、了解代码实际运行情况、获取应用崩溃前活动历史等问题。它性能开销在 2% - 10% 之间,使用时无需修改应用程序,能以…...

Windows 11/10下,Microsoft Store打不开?手把手教你用CheckNetIsolation命令批量解除UWP网络隔离

Windows 11/10下Microsoft Store无法连接的终极解决方案:CheckNetIsolation命令详解当你在Windows 11或10上突然发现Microsoft Store无法加载内容,或者Edge浏览器部分网页打不开,而其他网络连接却正常时,这很可能是因为UWP应用的网…...

告别图片搜索焦虑:如何在本地硬盘中秒级找到任何相似图片

告别图片搜索焦虑:如何在本地硬盘中秒级找到任何相似图片 【免费下载链接】ImageSearch 基于.NET10的本地硬盘千万级图库以图搜图案例Demo和图片exif信息移除小工具分享 项目地址: https://gitcode.com/gh_mirrors/im/ImageSearch 还在为硬盘里成千上万的图片…...

Applite:3步告别命令行,让Mac应用管理变得如此简单

Applite:3步告别命令行,让Mac应用管理变得如此简单 【免费下载链接】Applite User-friendly GUI macOS application for Homebrew Casks 项目地址: https://gitcode.com/gh_mirrors/ap/Applite 你是否曾因安装一个应用而被迫打开终端,…...

免费快速搞定CTF MISC难题:5个PuzzleSolver实战技巧让你秒变大神

免费快速搞定CTF MISC难题:5个PuzzleSolver实战技巧让你秒变大神 【免费下载链接】PuzzleSolver 一款针对CTF竞赛MISC的工具~ 项目地址: https://gitcode.com/gh_mirrors/pu/PuzzleSolver 你是不是每次参加CTF比赛,看到MISC题目就头疼&#xff1f…...

qmc-decoder深度解析:高效解密QQ音乐加密格式的技术架构与实践

qmc-decoder深度解析:高效解密QQ音乐加密格式的技术架构与实践 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 在数字音乐版权保护的背景下,QQ音乐采…...

3步掌握终极AMD Ryzen调试工具:免费解锁硬件深层控制

3步掌握终极AMD Ryzen调试工具:免费解锁硬件深层控制 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://git…...

Chatbox终极主题定制指南:打造专属AI交互界面

Chatbox终极主题定制指南:打造专属AI交互界面 【免费下载链接】chatbox Powerful AI Client 项目地址: https://gitcode.com/GitHub_Trending/ch/chatbox 你是否曾经在深夜编码时,被刺眼的浅色界面晃得眼睛发疼?又或者,你是…...

大语言模型驱动的定性研究编码自动化:GATOS工作流实践指南

1. 项目概述:当大语言模型遇见定性研究编码如果你做过定性研究,比如分析几百份开放式问卷、访谈转录稿,或者处理海量的用户反馈,你肯定对“编码”这个环节又爱又恨。爱的是,它能将杂乱无章的文本转化为结构化的见解&am…...

终极解决方案:如何用qmc-decoder快速解锁QQ音乐加密格式

终极解决方案:如何用qmc-decoder快速解锁QQ音乐加密格式 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 你是否曾经下载了QQ音乐,却发现那些.qmc3、…...

如何用DeepL Chrome翻译插件打破语言障碍:从安装到精通的完整指南

如何用DeepL Chrome翻译插件打破语言障碍:从安装到精通的完整指南 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 你是否经常遇到需要阅读外文网页却苦…...

5分钟掌握qmcdump:解锁QQ音乐加密音频的终极指南

5分钟掌握qmcdump:解锁QQ音乐加密音频的终极指南 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 你是否曾经…...

Rusted PackFile Manager:免费创建全面战争模组的终极工具

Rusted PackFile Manager:免费创建全面战争模组的终极工具 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址: https:/…...

逃离塔科夫SPT-AKI存档编辑器:终极离线版角色管理解决方案

逃离塔科夫SPT-AKI存档编辑器:终极离线版角色管理解决方案 【免费下载链接】SPT-AKI-Profile-Editor Программа для редактирования профиля игрока на сервере SPT-AKI 项目地址: https://gitcode.com/gh_mirro…...

NLP文本预处理全流程实战:从数据清洗到向量化的工程实践指南

1. 项目概述:从文本到智能的桥梁在人工智能的众多分支中,自然语言处理(NLP)一直是最具挑战性也最引人入胜的领域之一。它的核心目标直白而宏大:让机器能像人一样理解、运用和生成语言。这听起来像是科幻小说的情节&…...

Mermaid在线编辑器:3步掌握技术文档图表制作的终极指南

Mermaid在线编辑器:3步掌握技术文档图表制作的终极指南 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live-edito…...

5分钟实现位图到矢量图转换:Potrace多色彩矢量化技术深度解析

5分钟实现位图到矢量图转换:Potrace多色彩矢量化技术深度解析 【免费下载链接】vectorizer Potrace based multi-colored raster to vector tracer. Inputs PNG/JPG returns SVG 项目地址: https://gitcode.com/gh_mirrors/ve/vectorizer 在数字图像处理领域…...

3步掌握tracetcp:Windows平台专业TCP路由追踪工具完全指南

3步掌握tracetcp:Windows平台专业TCP路由追踪工具完全指南 【免费下载链接】tracetcp tracetcp. Traceroute utility that uses tcp syn packets to trace network routes. 项目地址: https://gitcode.com/gh_mirrors/tr/tracetcp 在Windows网络诊断领域&am…...

5分钟终极指南:如何用KMS_VL_ALL_AIO一键搞定Windows和Office激活难题

5分钟终极指南:如何用KMS_VL_ALL_AIO一键搞定Windows和Office激活难题 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows激活烦恼吗?每次重装系统后都要到处寻…...

微信直连 OpenClaw,手机发指令操控电脑,效率炸裂

下载地址:OpenClaw Windows 一键部署包 https://xiake.yun/api/download/package/16?promoCodeIV9D9D5198DC OpenClaw 绑定微信教程 1:软件下载完成界面 2:选择右上角设置 3:选择聊天配置 4:选择右边展开&#xff…...

OpenCore Legacy Patcher终极指南:4步让老款Mac免费升级最新macOS系统

OpenCore Legacy Patcher终极指南:4步让老款Mac免费升级最新macOS系统 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 还在为你的老款Mac无法升级…...

手把手教你用Python监控自己的ETH钱包地址是否‘被碰撞’(含简易脚本)

用Python构建ETH钱包安全监控系统:从API调用到风险预警实战最近在整理自己的数字资产时,突然意识到一个问题:我们平时使用的ETH钱包地址,是否可能因为公开交易记录而暴露在风险中?这个问题让我开始研究如何通过技术手段…...

跨平台资源下载终极指南:轻松获取视频号、抖音、直播流等全网资源

跨平台资源下载终极指南:轻松获取视频号、抖音、直播流等全网资源 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader …...

如何在Windows上快速安装苹果设备驱动:告别连接烦恼的完整指南

如何在Windows上快速安装苹果设备驱动:告别连接烦恼的完整指南 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.co…...

3分钟掌握QMC音频解密:qmc-decoder实战指南与算法深度解析

3分钟掌握QMC音频解密:qmc-decoder实战指南与算法深度解析 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 在数字音乐时代,你是否曾因QQ音乐加密格式…...

如何免费实现NVIDIA显卡专业级色彩校准:novideo_srgb终极指南

如何免费实现NVIDIA显卡专业级色彩校准:novideo_srgb终极指南 【免费下载链接】novideo_srgb Calibrate monitors to sRGB or other color spaces on NVIDIA GPUs, based on EDID data or ICC profiles 项目地址: https://gitcode.com/gh_mirrors/no/novideo_srgb…...