[翻译] Effective C++, 3rd Edition, Item 13: 使用 objects(对象)管理资源

H3C设备VRF配置实战:5步搞定多业务网络隔离(附排错技巧) 本文详细介绍了在H3C设备上配置VRF(虚拟路由转发)实现多业务网络隔离的实战方法。通过五步配置流程,从创建VPN-instance、绑定接口到配置独立路由表,帮助网络工程师在单台设备上构建逻辑隔离的企业级网络,并分享了高级路由配置与常见排错技巧。 阅读详情

Item 13: 使用 objects(对象)管理资源

作者:Scott Meyers

译者:fatalerror99 (iTePub's Nirvana)

发布:http://blog.youkuaiyun.com/fatalerror99/

假设我们和一个模拟投资(例如,股票,债券等)的库一起工作,各种各样的投资形式从一个 root class(根类)Investment 继承出来:

class Investment { ... };            // root class of hierarchy of
                                     // investment types

进一步假设这个库为我们提供特定 Investment objects(对象)的方法是通过一个 factory function(工厂函数)(参见 Item 7)达成的:

Investment* createInvestment();      // return ptr to dynamically allocated
                                     // object in the Investment hierarchy;
                                     // the caller must delete it
                                     // (parameters omitted for simplicity)

就像注释指出的,当 createInvestment 函数返回的 object(对象)不再使用时,由 createInvestment 的调用者负责删除它。那么,考虑,写一个函数 f 来履行这个职责:

void f()
{
  Investment *pInv = createInvestment();         // call factory function
  ...                                            // use pInv
  delete pInv;                                   // release object
}

这个看上去没什么问题,但是有几种 f 在删除它从 createInvestment 得到的 investment object(对象)时失败的情况。有可能在这个函数的 "..." 部分的某处有一个提前出现的 return 语句。如果这样一个 return 被执行,控制流程就再也无法到达 delete 语句。还可能发生的一个类似情况是如果 createInvestment 的使用和 delete 在一个循环里,而这个循环以一个 continue 或 goto 语句提前退出。还有,"..." 中的一些语句可能抛出一个 exception(异常)。如果这样,控制流程也不会到达那个 delete。无论那个 delete 被如何跳过,我们泄漏的不仅仅是容纳 investment object(对象)的内存,还包括那个 object(对象)持有的任何资源。

当然,小心谨慎地编程能防止诸如此类的错误,但考虑到这些代码可能会随着时间的流逝而发生变化。为了对软件进行维护,一些人可能会在没有完全把握对这个函数的资源管理策略的其它部分的影响的情况下增加一个 return 或 continue 语句。尤有甚者,f 的 "..." 部分可能调用了一个从不惯于抛出 exception(异常)的函数,但是在它被“改良”后突然这样做了。信赖 f 总能到达它的 delete 语句根本靠不住。

为了确保 createInvestment 返回的资源总能被释放,我们需要将那些资源放入一个 object(对象)中,这个 object(对象)的 destructor(析构函数)在控制流程离开 f 的时候会自动释放资源。实际上,这只是本 Item 背后的思想的一半:通过将资源放到 objects(对象)的内部,我们可以依赖 C++ 的 automatic destructor invocation(自动的析构函数调用)来确保资源被释放。(过一会儿我们要讨论本 Item 的思想的另一半。)

多数资源都是在堆上 dynamically allocated(动态分配)的,在一个单独的 block(块)或 function(函数)内使用,而且应该在控制流程离开那个 block(块)或 function(函数)的时候被释放。标准库的 auto_ptr 正是为这种情形量体裁衣的。auto_ptr 是一个 pointer-like object(类指针对象)(一个 smart pointer(智能指针)),它的 destructor(析构函数)自动在它指向的东西上调用 delete。下面就是如何使用 auto_ptr 来预防 f 的潜在的资源泄漏:

void f()
{
  std::auto_ptr<Investment> pInv(createInvestment());  // call factory
                                                       // function
  ...                                                  // use pInv as
                                                       // before
}                                                      // automatically
                                                       // delete pInv via
                                                       // auto_ptr's dtor

这个简单的例子示范了使用 objects(对象)管理资源的两个重要的方面:

  • 获取资源后立即移交给 resource-managing objects(资源管理对象)。前面,createInvestment 返回的资源被用来初始化即将用来管理它的 auto_ptr。实际上,因为获取一个资源并在同一个语句中初始化一个 resource-managing object(资源管理对象)是如此常见,所以使用 objects(对象)管理资源的观念常常被称为 Resource Acquisition Is Initialization (RAII)。有时被获取的资源是被赋值给 resource-managing object(资源管理对象),而不是初始化它们的,但这两种方法都是在获取资源的同时就立即将它移交给一个 resource-managing object(资源管理对象)。
  • resource-managing objects(资源管理对象)使用它们的 destructors(析构函数)确保资源被释放。因为当一个 object(对象)被销毁时(例如,当一个 object(对象)离开其活动范围)会自动调用 destructors(析构函数),无论控制流程是怎样离开一个 block(块)的,资源都会被正确释放。如果释放资源的动作会导致 exceptions(异常)被抛出,事情就会变得棘手,但是那是 Item 8 讲述的内容,所以在这里我们不必担心它。

因为当一个 auto_ptr 被销毁的时候,会自动删除它所指向的东西,所以不要让超过一个的 auto_ptr 指向一个 object(对象)非常重要。如果发生了这种事情,那个 object(对象)就会被删除超过一次,而且会让你的程序通过捷径进入 undefined behavior(未定义行为)。为了防止这样的问题,auto_ptrs 具有不同寻常的特性:拷贝它们(通过 copy constructor(拷贝构造函数)或者 copy assignment operator(拷贝赋值运算符))就是将它们置为空,而拷贝的指针取得资源的唯一所有权。

std::auto_ptr<Investment>                 // pInv1 points to the
  pInv1(createInvestment());              // object returned from
                                          // createInvestment

std::auto_ptr<Investment> pInv2(pInv1);   // pInv2 now points to the
                                          // object; pInv1 is now null

pInv1 = pInv2;                            // now pInv1 points to the
                                          // object, and pInv2 is null

这个奇怪的拷贝行为,增加了潜在的需求,就是通过 auto_ptrs 管理的资源必须绝对没有超过一个 auto_ptr 指向它们,这也就意味着 auto_ptrs 不是管理所有 dynamically allocated resources(动态分配资源)的最好方法。例如,STL containers(容器)要求其内含物能表现出“正常的”拷贝行为,所以 auto_ptrs 的容器是不被允许的。

相对于 auto_ptrs,另一个可选方案是一个 reference-counting smart pointer (RCSP)(引用计数智能指针)。一个 RCSP 是一个能持续跟踪有多少 objects(对象)指向一个特定的资源,并能够在不再有任何东西指向那个资源的时候自动删除它的 smart pointer(智能指针)。就这一点而论,RCSPs 提供的行为类似于 garbage collection(垃圾收集)的行为。然而,与 garbage collection(垃圾收集)不同的是, RCSPs 不能打破循环引用(例如,两个没有其它使用者的 objects(对象)互相指向对方)。

TR1 的 tr1::shared_ptr(参见 Item 54)是一个 RCSP,所以你可以这样写 f:

void f()
{
  ...

  std::tr1::shared_ptr<Investment>
    pInv(createInvestment());             // call factory function
  ...                                     // use pInv as before
}                                         // automatically delete
                                          // pInv via shared_ptr's dtor

这里的代码看上去和使用 auto_ptr 的几乎相同,但是拷贝 shared_ptrs 的行为却自然得多:

void f()
{
  ...

  std::tr1::shared_ptr<Investment>          // pInv1 points to the
    pInv1(createInvestment());              // object returned from
                                            // createInvestment

  std::tr1::shared_ptr<Investment>          // both
pInv1 and pInv2 now
    pInv2(pInv1);                           // point to the object

  pInv1 = pInv2;                            // ditto — nothing has
                                            // changed
  ...
}                                           // pInv1 and pInv2 are
                                            // destroyed, and the
                                            // object they point to is
                                            // automatically deleted

因为拷贝 tr1::shared_ptrs 的工作“符合预期”,它们能被用于 STL containers(容器)以及其它和 auto_ptr 的非正统的拷贝行为不相容的环境中。

可是,不要误解,本 Item 不是关于 auto_ptr,tr1::shared_ptr 或任何其它种类的 smart pointer(智能指针)的。而是关于使用 objects(对象)管理资源的重要性的。auto_ptr 和 tr1::shared_ptr 仅仅是做这些事的 objects(对象)的例子。(关于 tr1::shared_ptr 的更多信息,请参考 Item 14,18 和 54。)

auto_ptr 和 tr1::shared_ptr 都在它们的 destructors(析构函数)中使用 delete,而不是 delete []。(Item 16 描述两者的差异。)这就意味着将 auto_ptr 或 tr1::shared_ptr 用于 dynamically allocated arrays(动态分配数组)是个馊主意,可是,很遗憾,那居然可以编译:

std::auto_ptr<std::string>                       // bad idea! the wrong
  aps(new std::string[10]);                      // delete form will be used

std::tr1::shared_ptr<int> spi(new int[1024]);    // same problem

你可能会吃惊地发现 C++ 中没有可用于 dynamically allocated arrays(动态分配数组)的类似 auto_ptr 或 tr1::shared_ptr 这样的东西,甚至在 TR1 中也没有。那是因为 vector 和 string 几乎总是能代替 dynamically allocated arrays(动态分配数组)。如果你依然觉得有可用于数组的类似 auto_ptr 和 tr1::shared_ptr 的 classes(类)更好一些的话,可以去看看 Boost(参见 Item 55)。在那里,你将如愿以偿地找到 boost::scoped_array 和 boost::shared_array 两个 classes(类)提供你在寻找的行为。

本 Item 的关于使用 objects(对象)管理资源的指导间接表明:如果你手动释放资源(例如,使用 delete,而不是在一个 resource-managing class(资源管理类)中),你就是在自找麻烦。像 auto_ptr 和 tr1::shared_ptr 这样的 pre-canned resource-managing classes(预制资源管理类)通常会使遵循本 Item 的建议变得容易,但有时,你使用了一个资源,而这些 pre-fab classes(预加工类)不能如你所愿地做事。如果碰上这种情况,你就需要精心打造你自己的 resource-managing classes(资源管理类)。那也并非困难得可怕,但它包含一些需要你细心考虑的微妙之处。那些需要考虑的事项是 Item 14 和 15 的主题。

作为最后的意见,我必须指出 createInvestment 的 raw pointer(裸指针)的返回形式就是一份 resource leak(资源泄漏)的请帖,因为调用者忘记在他们取回来的指针上调用 delete 实在是太容易了。(即使他们使用一个 auto_ptr 或 tr1::shared_ptr 来实行 delete,他们仍然必须记住将 createInvestment 的返回值存储到一个 smart pointer object(智能指针对象)中。)对付这个问题调用需要改变 createInvestment 的接口,这是我在 Item 18 中安排的主题。

Things to Remember

  • 为了防止 resource leaks(资源泄漏),使用 RAII objects(对象),在 RAII objects(对象)的 constructors(构造函数)中获取资源并在它们的 destructors(析构函数)中释放它们。
  • 两个通用的 RAII classes(类)是 tr1::shared_ptr 和 auto_ptr。tr1::shared_ptr 通常是更好的选择,因为它的拷贝时的行为是符合直觉的。拷贝一个 auto_ptr 是将它置为空。
LED灯闪烁实验:代码集成 LED灯闪烁实验已经全部完成,在该实验中使用了较多的工具链,涉及底层软件、建模、软件编译等。首先,通过STM32CubeMX工具进行STM32底层软件配置,可以大大减少手写代码的工作量。另外由于做了可视化,也降低了STM32的上手难度,提升效率。利用Simulink建模,可以在PC环境下验证应用层算法的正确性而不依赖于具体控制器,实现应用层算法和底层软件、控制器硬件的解耦。另外,图形化的建模方式也更加有利于开发者思考与分析,大量的封装库文件也可以降低开发的工作量。 阅读详情

相关推荐

「点燃我,温暖你」用Python制作一个动态爱心效果

最近「点燃我,温暖你」这部剧非常火,讲述的是程序员的爱情故事。其中陈飞宇饰演的男主李峋,在剧中用程序做出的爱心跳动效果,非常炫。

Modeler_xiaoyu的博客 1万+

[翻译] Effective C++, 3rd Edition, Item 17: 在 standalone statements(独立语句)中将 new 出来的 objects(对象)存入 smart pointers(智能指针)

Item 17: 在 standalone statements(独立语句)中将 new 出来的 objects(对象)存入 smart pointers(智能指针)作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/假设我们有一个函数用于取得我们的 pr

艺术编程 3584

保姆级教程:在Windows/Mac上搞定SAM 3的权重和BPE文件下载与配置

本文提供了一份详细的SAM 3权重和BPE文件下载与配置指南,特别针对国内开发者遇到的下载缓慢和配置错误问题。通过国内镜像源快速获取文件,并详细介绍了环境检查、文件下载、路径配置及常见问题解决方案,帮助开发者高效完成SAM 3的部署与使用。

weixin_42547431的博客 551

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 254

从特斯拉到蔚来:拆解主流智能汽车的车联网架构,看它们如何实现‘车、路、云’协同

本文深度解析了特斯拉、蔚来等主流智能汽车的车联网架构,详细拆解了其‘车、路、云’协同的技术实现。从车内网络、车际通信到云端协同,分析了通信技术、系统架构等关键技术选择,揭示了不同厂商如何通过差异化布局构建竞争优势。

weixin_42525289的博客 580

ANSYS APDL实战:手把手教你搞定电磁-热耦合分析(附完整命令流)

本文通过一个工业感应加热线圈的实战案例,手把手教你使用ANSYS APDL完成电磁-热耦合分析。内容涵盖从几何建模、材料定义、网格划分到加载求解及后处理的完整流程,重点讲解了使用PLANE13单元进行双向耦合场分析的方法与命令流调试技巧,助力工程师快速掌握这一核心仿真能力。

weixin_29284201的博客 427

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 394

工程师必看:如何用定时截尾试验快速验证产品MTBF(附真实案例解析)

本文为硬件工程师详细解析了如何运用定时截尾试验快速验证产品MTBF(平均无故障工作时间)。通过七步实战法,结合工业物联网网关的真实案例,阐述了从参数设定、试验执行到结果判读的完整流程,并提供了MATLAB脚本实现自动化计算与可视化,帮助工程师在有限时间内科学评估产品可靠性。

weixin_29243063的博客 498

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 349

解决Android UVCCamera stopPreview 报错 崩溃 闪退 问题

在使用libuvccamera库的UVCCamera时,经常在调用stopPreview关闭预览的时候,app直接崩溃闪退了,经过综合各种修改源码的方案,已解决这个问题,以下请参考: 首先找到android_usbfs.c,linux_usbfs.c两个原文件,在两个文件中都可以找到这段代码,按如下示例修改: 修改前: for (i = 0; i < num_urbs; i++) { if (urb == tpriv->iso_urbs[i]) { urb_idx = i + 1;

hanye2020的博客 3576

YOLO格式数据集划分

YOLO格式的数据集划分 标题标签格式txt import os import cv2 import random from PIL import Image # os.makedirs('labels_train') # os.makedirs('labels_val') img_train_path ='./img_train/' #图片训练集保存路径 img_val_path = './img_val/' #图片验证集保存路径 labels_train_path = './labels_t

weixin_51154380的博客 3308

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 88

RT-DETR-R18 的轻量化 Trick:剪枝与量化在模型中的应用

RT-DETR-R18轻量化技术通过结构化剪枝、混合精度量化和知识蒸馏的组合优化,实现了显著模型压缩效果。摘要如下: RT-DETR-R18模型通过创新轻量化技术组合,在保持46.2% mAP精度的前提下,将模型大小压缩至2.1MB(压缩率78%),计算量降至3.2 GFLOPs(减少78.2%),实现移动端28ms实时推理(加速37.8%)。核心技术包括:1)渐进式结构化剪枝系统,通过L1范数重要性评估和动态剪枝调度;2)混合精度量化策略,对关键层保留FP16精度;3)教师-学生知识蒸馏框架保持模型表达能

走向CTO的路上... 1192

【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基

本文系统梳理C++类与对象的核心知识点,涵盖类的定义、访问限定符(public/private)、类作用域、对象实例化及内存布局。重点解析封装思想、this指针机制、空类大小为1字节的原因,以及类与对象在内存中的存储差异。通过对比C语言结构体与C++类,揭示面向对象设计的优势:数据保护、接口统一、命名隔离与代码可维护性提升。内容由浅入深,适合作为学习笔记与复习参考。

2602_95684935的博客 493

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 307

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C++ 运行时多态与虚函数机制全面剖析【面试重点】

构成C++ 运行时多态必须是基类的指针或者引用调用虚函数。被调用的函数必须是虚函数,并且派生类必须对该虚函数完成重写/覆盖(Override)。只有基类的指针或引用才能既指向基类对象,又指向派生类对象(切片机制);而只有完成了虚函数重写,派生类与基类才具备不同的函数行为,达到“指向谁就调用谁”的效果。在类成员函数的前面加上virtual关键字修饰,该成员函数就成为了虚函数。public:// 成员函数前加 virtual 修饰,声明为虚函数。

Fuyo_0209的博客 450

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

#SQLite 数据库笔记一:(概念 / 终端指令 / SQL 语句 / C 编程 / 回调函数)

数据库 = 数据的仓库,假设数据是海量。能力说明存储数据持久化保存,程序退出数据还在统计数据、分组、排序数据管理增、删、改、查(CRUD)嵌入式设备上也会用数据库(单片机网关、路由器、工业 HMI 都常见),因为 sqlite 体积小、无需服务进程、单文件即可。数据库 = 库 > 表 > 记录(行) > 字段(列)sqlite3 = 开源、C 写的、单文件、免安装、最多 2T 的嵌入式关系型数据库。

lwq20051110的博客 251

1-10 PostgreSQL中多表连接全解:inner/left/right/full/cross join

本文基于 PostgreSQL 15+ 完整拆解 5 种主流连接:内连接、左连接、右连接、全连接、笛卡尔连接。结合可落地的测试数据,演示每种连接的执行逻辑、返回结果,重点剖析 NULL 值对 JOIN 匹配的核心影响,彻底解决多表连接数据丢失、匹配异常、结果错乱的问题。

zhangjw34的专栏 105

【C++ 基础入门】C++继承(下):问题、底层原理与组合

C++继承(菱形继承的问题、虚继承原理、继承与组合、构造顺序)

2601_96587588的博客 802

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级 备考:莫队算法离线区间查询详解

备赛进行时:第十八届蓝桥杯软件赛报名已于 2026-10-08 10:00 开启、12-18 14:00 截止,省赛定在 2027-04-10(C/C++·Python 程序设计 9:00–13:00);中国电子学会 2026 年 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名 9/23–12/2 16:00、统考 12-12;全国青少年信息素养大赛 2026—2027 赛季算法应用主题赛也已进入复盘练兵窗口。

IT_Scratch的博客 170

c++ explicit关键字详解

explicit。

拒绝AI文,努力在AI时代写出感动人心的好文章 151

825 mW 顶上 212 °C:ASM491S 的 105 °C/W、250 mA 短路电流与热关断

25 °C 环境里结温 34.1 °C,125 °C 环境里结温 134.1 °C——后者已经离 150 °C 只有 16 °C 了,但还在范围内。换个角度看同一件事:从 25 °C 和从 125 °C 起算,温升都是 86.6 °C,但一个到 111.6 °C(还在范围内),一个到 211.6 °C(远远超限)。这个算例里 20 °C/W 是我假设的,实际值取决于机壳材料、密封程度、有没有风扇,跨度可以从 5 °C/W 到 50 °C/W 以上。外面 50 °C 的机箱,盒内就是 63.9 °C。

ANSILIC的博客 393

《C++ 项目:手写大模型接入 SDK》Gemini接口设计(上):初始化、全量响应实现和测试

本文系统完成了Gemini模型通过OpenAI兼容API的接入开发,基于Apifox验证接口规范,设计并实现GeminiProvider类,涵盖初始化、状态检测、全量响应等核心功能。重点处理了代理配置强制校验、Bearer鉴权、JSON序列化与响应解析等工程细节,并通过GTest与CMake完成单元测试,验证链路可用性。项目遵循策略模式,保持与DeepSeek、ChatGPT等模型的统一抽象接口,显著提升SDK可扩展性。

2501_91275995的博客 398

【容斥原理计数】题解:P9489 ZHY的表示法_容斥原理_计数问题_前缀和问题转化_算法竞赛C++

给定 $ n $ 个正整数,求区间 $[l,r]$ 中有多少正整数 $ x $ 可表示为 $ \sum \lfloor \frac{y}{x_i} \rfloor $。通过二分确定最大 $ y $,转化为求 $ 1 \sim H $ 中是某些 $ x_i $ 倍数的数的个数,利用容斥原理与 DFS 枚举子集计算,结合 LCM 预判剪枝及去重优化,时间复杂度 $ O(2^n \log V) $,可高效处理 $ r \le 10^9 $ 的数据。

YLCHUP的博客 106

头歌 数据结构——C&C++线性表实训

本系列任务围绕线性表的链式实现,依次完成顺序构建、逆序构建、排序插入、查找、删除、求长度及栈、队列、集合等应用。通过动态内存分配与指针操作,掌握单链表的基本操作与实际应用,涵盖插入、删除、遍历、搜索等核心功能,最终实现数据结构在典型场景中的灵活运用。

一名敲代码的苦13程序员 244

字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)

本题核心思想是:最少移动步数 = 总长度 - 可保留的最长连续子串长度。未移动字母在T中必须为连续子串,在S中需保持相对顺序(即子序列)。通过枚举T的所有连续子串起点,贪心匹配S中的对应字符,求出最长可保留长度L,答案即为n−L。时间复杂度O(n²),空间复杂度O(n),适用于n≤1000。

冻柠茶飞冰走茶 592
上一篇: [翻译] Effective C++, 3rd Edition, Item 12: 拷贝一个 object(对象)的所有 parts(构件)
下一篇: [翻译] Effective C++, 3rd Edition, Item 14: 谨慎考虑 resource-managing classes(资源管理类)中的拷贝行为
fatalerror99
博客等级 码龄24年 166粉丝 20原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值