C++智能指针详解:unique_ptr、shared_ptr与weak_ptr实战指南
1. 智能指针从手动管理到自动化的内存革命在C的世界里指针是通往内存的直接桥梁它赋予了我们无与伦比的灵活性但也带来了臭名昭著的“内存泄漏”和“悬空指针”问题。手动管理内存就像在悬崖边行走稍有不慎程序就会崩溃。我见过太多项目因为一个delete的遗漏导致服务在线上运行数周后内存耗尽排查起来如同大海捞针。正是为了解决这些痛点智能指针应运而生它不仅仅是语法糖更是一种编程范式的转变将程序员从繁琐且易错的内存管理细节中解放出来让资源管理变得确定和自动化。简单来说智能指针是一个类模板它封装了原始指针并利用RAIIResource Acquisition Is Initialization资源获取即初始化机制在其生命周期结束时自动释放所管理的资源。无论你是刚接触C的新手还是正在准备面试、希望深入理解核心机制的开发者掌握智能指针都是迈向稳健、现代C编程的必经之路。接下来我们就深入拆解C标准库提供的几种智能指针看看它们各自扮演什么角色以及如何在实际项目中做出选择。2. 智能指针家族全解析unique_ptr,shared_ptr,weak_ptrC11标准引入了智能指针主要包含std::unique_ptr、std::shared_ptr和std::weak_ptr。它们位于memory头文件中。理解它们的关键在于理解其背后的所有权模型。2.1std::unique_ptr独占所有权的守卫unique_ptr如其名独占其所指向对象的所有权。同一时刻只能有一个unique_ptr指向一个给定的对象。当这个unique_ptr被销毁例如离开作用域时它所管理的对象也会被自动删除。核心特性与使用场景独占所有权无法进行拷贝构造和拷贝赋值确保了所有权的唯一性。这是它最根本的特性。移动语义所有权可以通过std::move进行转移。转移后源unique_ptr变为空指针。轻量高效由于没有引用计数的开销其性能开销与原始指针几乎无异。自定义删除器可以指定一个函数或函数对象来替代默认的delete操作用于管理非new分配的资源如fopen返回的FILE*。典型代码示例#include memory #include iostream class MyClass { public: MyClass() { std::cout MyClass constructed\n; } ~MyClass() { std::cout MyClass destroyed\n; } void doSomething() { std::cout Doing something...\n; } }; void testUniquePtr() { // 创建一个unique_ptr管理一个MyClass对象 std::unique_ptrMyClass ptr1(new MyClass()); // auto ptr1 std::make_uniqueMyClass(); // C14推荐方式更安全 ptr1-doSomething(); // 使用-操作符访问成员 // 编译错误无法拷贝 // std::unique_ptrMyClass ptr2 ptr1; // 所有权转移 std::unique_ptrMyClass ptr3 std::move(ptr1); if (!ptr1) { std::cout ptr1 is now null after move.\n; } ptr3-doSomething(); // 函数结束时ptr3销毁自动删除MyClass对象 }实操心得与避坑指南优先使用std::make_uniqueC14及以上它比直接使用new更安全。make_unique将对象构造和智能指针创建合并为一个原子操作避免了因异常导致的内存泄漏。例如func(std::unique_ptrT(new T), otherFunc())如果otherFunc()抛出异常new T分配的内存可能泄漏。而func(std::make_uniqueT(), otherFunc())则不会。默认选择在大多数不需要共享所有权的场景下unique_ptr应该是你的首选。它语义清晰没有额外开销能明确表达资源生命周期。用于实现PIMPLPointer to IMPLementation惯用法这是unique_ptr的一个经典应用场景有助于隐藏实现细节减少编译依赖。2.2std::shared_ptr共享所有权的协作团队当多个对象需要共享同一个资源且无法确定谁最后使用它时shared_ptr就派上用场了。它通过引用计数来管理所有权。每多一个shared_ptr指向该对象引用计数就加一每有一个shared_ptr被销毁或重置引用计数就减一。当引用计数变为零时管理的内存被自动释放。核心特性与使用场景共享所有权支持拷贝和赋值多个shared_ptr可以指向同一个对象。引用计数内部维护一个控制块通常包含引用计数、弱引用计数和删除器有额外的内存和时间开销。循环引用风险这是shared_ptr最著名的陷阱。如果两个或多个shared_ptr相互指向形成环状结构它们的引用计数永远无法降到零导致内存泄漏。自定义删除器同样支持。典型代码示例#include memory #include iostream class Node { public: std::shared_ptrNode next; std::shared_ptrNode prev; // 使用shared_ptr可能导致循环引用 ~Node() { std::cout Node destroyed\n; } }; void testSharedPtr() { // 创建shared_ptr auto sp1 std::make_sharedint(42); // 引用计数 1 { auto sp2 sp1; // 拷贝引用计数 2 std::cout sp1 use_count: sp1.use_count() std::endl; // 输出 2 } // sp2离开作用域被销毁引用计数 1 std::cout sp1 use_count: sp1.use_count() std::endl; // 输出 1 // sp1离开作用域引用计数变为0内存释放 } // 循环引用示例错误示范 void circularReference() { auto nodeA std::make_sharedNode(); auto nodeB std::make_sharedNode(); nodeA-next nodeB; // nodeB 被 nodeA 和 nodeB 自己通过sp引用 nodeB-prev nodeA; // nodeA 被 nodeA 自己通过sp和 nodeB 引用 // 函数结束nodeA和nodeB的引用计数均为2减为1内存永不释放 }实操心得与避坑指南优先使用std::make_shared与make_unique类似它更安全并且通常效率更高因为它有可能将对象和控制块分配在连续的内存块中。警惕循环引用这是使用shared_ptr时必须时刻警惕的问题。当你设计具有双向关联或环形关系的类时如树节点的父指针、双向链表的节点如果使用shared_ptr相互持有就会形成循环引用。解决方案是引入weak_ptr。性能考量引用计数的增减是原子操作线程安全有性能开销。不要在不必要共享的地方滥用shared_ptr。如果生命周期很明确unique_ptr是更好的选择。不要用同一个原始指针初始化多个独立的shared_ptr这会导致多个控制块从而对同一内存进行多次释放。auto ptr new int; std::shared_ptrint sp1(ptr); std::shared_ptrint sp2(ptr); // 灾难2.3std::weak_ptr打破循环引定的观察者weak_ptr是为了解决shared_ptr的循环引用问题而生的。它指向一个由shared_ptr管理的对象但不增加该对象的引用计数。这意味着weak_ptr的存在不会阻止其所指对象的销毁。你可以把weak_ptr看作是一个“弱”引用或“观察者”。核心特性与使用场景不拥有所有权不控制对象生命周期不增加引用计数。需转换为shared_ptr才能使用通过lock()成员函数可以尝试获取一个指向对象的shared_ptr。如果对象还存在引用计数0则返回一个有效的shared_ptr并增加引用计数否则返回空的shared_ptr。用于解决循环引用在可能形成循环引用的地方将其中一个指针改为weak_ptr。典型代码示例修复循环引用#include memory #include iostream class NodeSafe { public: std::shared_ptrNodeSafe next; std::weak_ptrNodeSafe prev; // 将其中一个方向改为weak_ptr ~NodeSafe() { std::cout NodeSafe destroyed\n; } }; void testWeakPtr() { auto nodeA std::make_sharedNodeSafe(); auto nodeB std::make_sharedNodeSafe(); nodeA-next nodeB; nodeB-prev nodeA; // 这里只是弱引用不增加nodeA的引用计数 // 尝试通过weak_ptr访问对象 if (auto sharedPrev nodeB-prev.lock()) { // 尝试提升为shared_ptr std::cout Previous node is still alive.\n; // 可以使用sharedPrev访问对象 } else { std::cout Previous node has been destroyed.\n; } // 函数结束nodeB引用计数为1仅被nodeA-next持有nodeA引用计数为1仅被nodeA自己持有。 // 两者均能正常销毁无内存泄漏。 }实操心得与避坑指南检查lock()的返回值在使用weak_ptr::lock()获取shared_ptr后必须检查返回的shared_ptr是否为空。这是安全使用weak_ptr的铁律。缓存场景weak_ptr非常适合用于缓存。缓存持有对象的弱引用当需要时尝试提升。如果对象已被其他部分释放缓存项自动失效可以重新加载。观察者模式主题Subject持有观察者Observer的weak_ptr这样观察者可以在任意时刻销毁自己而不会导致主题持有悬空指针或阻止观察者析构。3. 核心区别对比与选型决策矩阵为了更直观地理解三者的区别我们可以从多个维度进行对比特性维度std::unique_ptrstd::shared_ptrstd::weak_ptr所有权模型独占所有权共享所有权无所有权弱引用拷贝/赋值禁止拷贝允许移动允许拷贝和赋值允许拷贝和赋值性能开销极小近乎原始指针较高原子引用计数较低但lock()有开销内存开销通常仅一个指针至少两个指针对象指针控制块指针同shared_ptr是否影响对象生命周期是唯一所有者是通过引用计数否主要用途独占资源、工厂函数返回值、PIMPL共享资源、缓存、需要共享所有权的复杂关系打破shared_ptr循环引用、缓存、观察者线程安全对象访问需外部同步引用计数操作原子安全对象访问需外部同步同shared_ptr选型决策流程问自己资源是否需要被多个部分共享否- 优先选择std::unique_ptr。这是最简单、最安全、最高效的选择。是- 进入第2步。问自己共享的各方中是否存在环形引用关系如A拥有BB也拥有A否- 可以使用std::shared_ptr。确保所有共享者都以shared_ptr形式持有。是- 必须引入std::weak_ptr。将环中的至少一个链接改为weak_ptr以打破循环引用。通常在父子关系、观察者等场景中将“父指向子”或“主题指向观察者”的指针设为weak_ptr。重要提示智能指针管理的是动态分配的对象即通过new分配的对象。对于栈对象、静态对象或成员对象不应使用智能指针。另外智能指针不能用于管理数组除非使用unique_ptrT[]但std::vector或std::array通常是更好的选择。4. 深入原理引用计数与控制块理解shared_ptr和weak_ptr的行为需要深入其背后的实现机制——控制块。一个典型的shared_ptr包含两个指针指向被管理对象的指针。指向控制块的指针。控制块通常包含强引用计数use_count当前有多少个shared_ptr共享对象所有权。此数归零时销毁被管理对象。弱引用计数weak_count当前有多少个weak_ptr指向该控制块。此数用于决定何时销毁控制块本身。注意弱引用计数不为零不会阻止对象销毁只会阻止控制块内存释放。删除器Deleter用于销毁对象的函数或函数对象。分配器Allocator可选用于分配控制块内存。make_shared的优势原理std::make_shared通常会执行一次内存分配同时为对象和控制块预留空间。这不仅能提升性能减少一次分配还能提高局部性。而直接使用std::shared_ptrT(new T)会进行两次分配一次给T一次给控制块。weak_ptr的lock()操作原理lock()函数会检查控制块中的强引用计数。如果use_count 0则说明对象还活着它会原子地增加强引用计数以防止在检查和使用之间对象被销毁并返回一个指向该对象的新的shared_ptr。如果use_count 0则直接返回一个空的shared_ptr。5. 实战中的常见陷阱与高级技巧即使理解了基本概念在实际编码中依然会遇到不少坑。这里记录几个我踩过或见别人踩过的典型问题。5.1 陷阱一误用get()函数所有智能指针都有一个get()成员函数它返回内部保存的原始指针。这个函数要慎用。auto sp std::make_sharedint(10); int* rawPtr sp.get(); // 危险操作1用这个原始指针创建另一个智能指针 std::shared_ptrint sp2(rawPtr); // 灾难sp和sp2有独立的控制块会双重释放。 // 危险操作2手动删除原始指针 // delete rawPtr; // 灾难sp在析构时会再次删除。核心原则get()返回的指针其生命周期绝对不应超过管理它的智能指针。仅用于向那些只接受原始指针的旧式API传递参数并且确保该API不会试图取得所有权或存储这个指针。5.2 陷阱二shared_ptr与this指针在类的成员函数中如果需要将this指针传递给一个接受shared_ptr的函数直接传递this是极其危险的。class BadClass { public: void registerSelf() { // 假设有一个全局注册表需要shared_ptrBadClass // someRegistry.add(shared_from_this()); // 错误不能直接构造。 } }; void someFunction(std::shared_ptrBadClass ptr) { /* ... */ } BadClass* obj new BadClass; someFunction(std::shared_ptrBadClass(obj)); // 如果其他地方也这样就双重释放了。正确做法让类继承自std::enable_shared_from_thisT并使用shared_from_this()成员函数。class GoodClass : public std::enable_shared_from_thisGoodClass { public: void registerSelf() { // 正确获取一个与当前对象所有权共享的shared_ptr auto selfPtr shared_from_this(); someRegistry.add(selfPtr); } }; // 注意对象必须已经被一个shared_ptr管理才能调用shared_from_this()。 auto goodObj std::make_sharedGoodClass(); goodObj-registerSelf(); // 安全5.3 技巧自定义删除器管理任意资源智能指针的强大之处在于它能管理任何资源只要提供对应的删除器。// 1. 管理文件句柄 #include cstdio { auto fileDeleter [](FILE* fp) { if(fp) fclose(fp); std::cout File closed.\n; }; std::unique_ptrFILE, decltype(fileDeleter) filePtr(fopen(test.txt, r), fileDeleter); // 使用filePtr.get()进行文件操作 // 离开作用域文件自动关闭 } // 2. 管理动态数组 (C17起unique_ptr支持数组但更推荐vector) { // 自定义删除器调用 delete[] auto arrayDeleter [](int* p) { delete[] p; }; std::unique_ptrint[], decltype(arrayDeleter) arrPtr(new int[100], arrayDeleter); // 对于shared_ptr管理数组需要显式指定删除器 std::shared_ptrint sp(new int[10], [](int* p) { delete[] p; }); }5.4 性能考量避免不必要的shared_ptr拷贝在函数参数传递时需要仔细考虑所有权语义。如果函数只是需要读取对象不需要取得或延长所有权传递const T或T*如果允许空指针。如果函数需要取得对象的所有权即接管生命周期传递std::unique_ptrT按值传递表示移动所有权。如果函数需要共享所有权即延长对象生命周期传递std::shared_ptrT通常按值传递。但注意按值传递会触发引用计数的原子递增/递减有开销。如果函数内部只是使用而不存储可以考虑传递const std::shared_ptrT来避免不必要的计数操作但要小心生命周期问题。void processByRef(const std::shared_ptrMyClass sp) { /* 只读不增加引用计数 */ } void takeOwnership(std::unique_ptrMyClass up) { /* 移动进来接管所有权 */ } void shareOwnership(std::shared_ptrMyClass sp) { /* 拷贝增加引用计数共享所有权 */ }6. 面试常见问题深度剖析智能指针是C面试的必考知识点。以下是一些高频问题的深度解析。Q1:shared_ptr是线程安全的吗这是一个经典的陷阱问题。答案是引用计数的操作是原子的线程安全的。但其所指向的对象的读写不是线程安全的。shared_ptr的拷贝、赋值、析构会修改引用计数这些操作是原子的所以多个线程同时拷贝/销毁指向同一对象的shared_ptr是安全的。但是通过shared_ptr访问其指向的对象如*sp 10;或调用成员函数和操作原始指针一样需要额外的同步机制如互斥锁来保证线程安全。Q2:weak_ptr如何知道对象是否被释放它不增加引用计数那它的存在会影响控制块的释放吗weak_ptr通过检查其关联的控制块中的强引用计数use_count来判断对象是否存活。当use_count为0时对象已被销毁。weak_ptr会增加控制块中的弱引用计数weak_count。即使对象被销毁use_count0只要还有weak_ptr存在weak_count0控制块本身就不会被释放。这是为了weak_ptr能安全地调用lock()需要访问控制块信息。当最后一个weak_ptr被销毁后控制块的内存才会被回收。Q3: 使用make_shared和直接使用new构造shared_ptr有什么区别为什么更推荐make_shared主要有三点区别异常安全make_shared将对象构造和智能指针创建合并是原子操作避免了因参数求值顺序导致的潜在内存泄漏如前文所述。性能make_shared通常只进行一次内存分配同时容纳对象和控制块减少了内存分配开销并可能提升缓存局部性。代码简洁性make_shared省去了显式的new代码更简洁。一个潜在的缺点由于对象和控制块内存是连续的只要还有weak_ptr存在控制块不能释放对象所占用的内存也无法被释放即使对象本身早已被销毁。而用new的方式对象和控制块是分开的对象内存可以在use_count0时立即释放。Q4: 如何设计一个类使其对象只能通过shared_ptr来管理一种常见的方法是将析构函数私有化或受保护并让类继承自std::enable_shared_from_this同时将构造函数公开或提供静态工厂函数。但更简洁的现代做法是将构造函数设为公开但只提供返回shared_ptr的静态工厂函数。class MyResource { public: // 静态工厂函数强制使用shared_ptr创建 static std::shared_ptrMyResource create() { // 使用make_shared可以调用私有构造函数 return std::make_sharedMyResource(); } void doWork() { /* ... */ } private: MyResource() default; // 构造函数私有 // ~MyResource() default; // 析构函数可以是公有的因为智能指针是友元 // 注意std::make_shared需要能访问构造函数但它不是友元。 // 实际上更简单的做法是只提供工厂函数不强制私有构造。 }; // 使用 auto res MyResource::create(); // 正确 // MyResource res2; // 错误构造函数不可访问掌握智能指针意味着你掌握了现代C资源管理的核心思想。从unique_ptr的独占与明确到shared_ptr的共享与协作再到weak_ptr的观察与解耦它们共同构建了一套安全、自动化的内存管理体系。在实际项目中我的体会是默认使用unique_ptr仅在确需共享时使用shared_ptr并用weak_ptr破解循环引用。多思考对象的所有权归属和生命周期这比盲目使用智能指针更重要。最后善用make_shared和make_unique它们是你写出更安全、更高效代码的好帮手。

相关新闻

Linux目录结构详解与最佳实践指南

Linux目录结构详解与最佳实践指南

1. Linux目录结构概述第一次登录Linux系统时,很多人都会被它那看似复杂的目录结构搞得晕头转向。与Windows系统将磁盘划分为C盘、D盘不同,Linux采用单一的树状目录结构,所有文件和设备都挂载在这个统一的文件系统下。这种设计理念源自Unix哲学…

2026/7/26 5:38:24 阅读更多 →
基于BQ25890H与MSP430的HVDCP动态调压快充方案实现

基于BQ25890H与MSP430的HVDCP动态调压快充方案实现

1. 项目概述与核心价值在智能手机、平板电脑这些我们每天重度使用的设备上,快充技术早已不是什么新鲜事。但你是否想过,当你插上那个支持快充的充电头时,手机和充电头之间究竟在“聊”些什么?为什么有些充电方案在高速充电时依然能…

2026/7/26 5:38:24 阅读更多 →
湖南百叶护栏,为何大家都在夸?

湖南百叶护栏,为何大家都在夸?

在建筑防护领域,百叶护栏早已从“功能件”升级为“颜值担当”。尤其是湖南地区,作为全国护栏产业的重要集群地,百叶护栏产品更是层出不穷。但为何在实际项目中,大家交口称赞的总是那几个品牌?是营销做得好,…

2026/7/26 5:37:23 阅读更多 →

最新新闻

从汇编中断到C++真题:系统程序员面试的底层原理与刷题指南

从汇编中断到C++真题:系统程序员面试的底层原理与刷题指南

1. 项目概述:从一道汇编指令到千道真题的硬核突围最近在技术社区和求职群里,一个看似“缝合”的标题引起了我的注意:“2024年最新中断程序设计_mov es [60h 4],ax(1),2024年最新为了跳槽强刷1000道C/C真题”。初看之下&#xff0c…

2026/7/26 5:46:27 阅读更多 →
终极Windows风扇控制指南:如何用FanControl打造个性化智能散热系统

终极Windows风扇控制指南:如何用FanControl打造个性化智能散热系统

终极Windows风扇控制指南:如何用FanControl打造个性化智能散热系统 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub…

2026/7/26 5:46:27 阅读更多 →
质谱仪腔体焊完漏气?精密激光封焊三步锁住超高真空

质谱仪腔体焊完漏气?精密激光封焊三步锁住超高真空

所谓质谱仪真空腔体的激光密封焊接,就是用精密激光束对不锈钢或可伐合金腔体的环缝进行气密性封装,使腔体内真空度达到10⁻⁶ Pa以下的超高真空级别——焊缝漏率需控制在10⁻⁹ Pam/s量级,相当于一个标准大气压下每年只允许漏入一粒芝麻体积的…

2026/7/26 5:46:27 阅读更多 →
终极指南:免费解锁macOS专业级音频控制的完整方案

终极指南:免费解锁macOS专业级音频控制的完整方案

终极指南:免费解锁macOS专业级音频控制的完整方案 【免费下载链接】eqMac macOS System-wide Audio Equalizer & Volume Mixer 🎧 项目地址: https://gitcode.com/gh_mirrors/eq/eqMac 你是否厌倦了macOS平淡无奇的音频体验?是否渴…

2026/7/26 5:46:27 阅读更多 →
3D打印骨植入物焊完孔隙塌了?精密控热三招保住

3D打印骨植入物焊完孔隙塌了?精密控热三招保住

所谓骨科植入物的多孔结构焊接,是指用精密激光束将3D打印的钛合金骨小梁多孔结构与实心承力部件(如椎间融合器端板、髋关节股骨柄连接座)进行冶金结合——既要焊牢,又不能把多孔结构"焊塌"了。2025年10月,华…

2026/7/26 5:46:27 阅读更多 →
2024年C++面试必备:克鲁斯卡尔算法核心原理与工业级实现详解

2024年C++面试必备:克鲁斯卡尔算法核心原理与工业级实现详解

1. 项目概述:为什么2024年还要深挖克鲁斯卡尔算法?如果你是一名C开发者,尤其是在准备面试或者希望夯实算法基础,看到“克鲁斯卡尔算法”这个名字,可能会觉得它有点“古典”。毕竟,图论算法那么多&#xff0…

2026/7/26 5:45:27 阅读更多 →

日新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

月新闻