当前位置:首页 > 博客 > 笔记 > 正文内容

Google-Specific Magic 谷歌独家黑科技

RWYQ阿伟2026-01-21笔记540

        我们采用多种技巧和工具来增强 C++ 代码的健壮性,同时我们在使用 C++ 的方式上也存在一些与别处不同的地方。

所有权与智能指针

        对于动态分配的对象,应确保其拥有唯一且固定的拥有者。在转移所有权时,应优先使用智能指针。

定义:

        “所有权” 是一种用于管理动态分配内存(及其他资源)的记账技术。所谓动态分配对象的“拥有者”,是指那些负责在对象不再需要时将其删除的对象或函数。所有权有时可以共享,在这种情况下,通常是最后一位拥有者负责将其删除。即使所有权不被共享,它也可以在代码的不同部分之间进行转移。

        “智能”指针 是行为类似于指针的类,例如它们会重载 * 和 -> 运算符。某些类型的智能指针可用于自动化所有权记账,以确保上述责任得到履行。

        std::unique_ptr 是一种表达对动态分配对象独占所有权的智能指针类型。当 std::unique_ptr 离开作用域时,其所拥有的对象会被自动删除。它不可复制,但可以通过移动(Move)来表示所有权的转移。

        std::shared_ptr 则是一种表达共享所有权的智能指针类型。std::shared_ptr 可以被复制,所有副本共同共享该对象的所有权。当最后一个 std::shared_ptr 被销毁时,对象才会被删除。

优点:

  • 若不采用某种所有权逻辑,实际上几乎不可能妥善管理动态分配的内存。

  • 转移对象的所有权通常比复制对象本身成本更低(况且有些对象根本无法复制)。

  • 相较于“借用”指针或引用的方式,转移所有权往往更为简单,因为它减少了双方用户协调对象生命周期的需要。

  • 智能指针通过显式地表达所有权逻辑,能够提升代码的可读性,使其具备自文档化和无歧义的特点。

  • 智能指针可以省去手动进行所有权记账的繁琐工作,从而简化代码,并彻底杜绝一大类潜在错误。

  • 对于常量对象而言,共享所有权相比深拷贝,往往是一种更简单且高效的替代方案。

缺点:

  • 所有权必须通过指针(无论是智能指针还是原始指针)来表示和转移。指针的语义比值语义要复杂得多,尤其是在 API 中:你不仅需要担心所有权,还必须处理别名、生命周期和可变性等诸多问题。

  • 值语义的性能开销常常被高估了,因此,所有权转移带来的那点性能收益,可能并不足以抵消其在可读性和复杂度上的代价。

  • 强制要求转移所有权的 API,会迫使使用者只能采用单一的内存管理模型。

  • 使用智能指针的代码,往往不够明确地指出资源释放的具体位置。

  • std::unique_ptr 使用移动语义来表达所有权转移,这可能比较复杂,让部分程序员感到困惑。

  • 共享所有权有时会成为一种诱人的选择,从而替代精心设计的所有权模型,但这往往会模糊系统的整体设计。

  • 共享所有权需要在运行时进行显式的引用记账,这可能带来性能开销。

  • 在某些情况下(例如循环引用),拥有共享所有权的对象可能永远不会被删除。

  • 智能指针并不是原始指针的完美替代品。

结论:

        如果必须进行动态分配,建议将所有权保留在执行分配操作的代码中。如果其他代码需要访问该对象,可以考虑传递一个副本,或者传递一个指针/引用(但不转移所有权)。

        建议使用 std::unique_ptr 来明确地表示所有权的转移。例如:

std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);

        除非有非常充分的理由,否则绝不要将你的代码设计为使用共享所有权。其中一个正当理由是为了避免昂贵的复制操作,但即便如此,你也只有在性能收益非常显著,且底层对象是不可变的情况下才应这么做(例如:std::shared_ptr<const Foo>)。

        如果你确实必须使用共享所有权,请务必优先使用 std::shared_ptr。

        严禁使用 std::auto_ptr,请改用 std::unique_ptr。

ccpplint(C++ 代码检查工具)

        使用 cpplint.py 来检测代码风格错误。

        cpplint.py 是一款读取源文件并识别其中多种风格错误的工具。虽然它并不完美,且存在误报(假阳性)和漏报(假阴性)的情况,但它依然是一个非常有价值的辅助工具。

        部分项目会提供通过其项目工具运行 cpplint.py 的具体说明。如果你所参与的项目没有提供此类说明,你可以单独下载 cpplint.py。


扫描二维码推送至手机访问。

版权声明:本文由阿伟的笔记本发布,如需转载请注明出处。

本文链接:https://www.awnotebook.com/post/952.html

标签: 笔记编程C++
分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。