C++ 读书笔记 Effective C++(二)

读书笔记:《Effective Modern C++(C++14)》 使用RAII(“Resource Acquisition Is Initialization,资源获得即初始化)包装thread,在析构时进行join。和闭包类存在于编译期,闭包存在于运行时。 阅读详情
18.  好的接口很容易被正确使用,不容易被误用。你应该在你的所有接口中努力达成这些性质。
       "促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容。
       “阻止误用”的办法包括建立新类型、限制类型上的操作,束缚对象值,以及消除客户的资源管理责任。
        tr1::shared_ptr支持定制型删除器。这可防范DLL问题,可被用来自动解除互斥锁等待。

19. Class的设计就是type的设计。在定义一个新type之前,请确定你已经考虑过本条款覆盖的所有讨论主题。

20.宁以pass-by-reference-to-const替代pass-by-value
    尽量以pass-by-reference-to-const替代pass-by-value.前者通常比较高效,并可避免切割问题。
    以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较合适。
21.必须返回对象时,别妄想返回其reference
     绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static 对象而有可能同时需要多个这样的对象。

22.切记将成员变量声明为private.这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性。
      protected并不比public更具封装性。

23.如果你需要为某个函数的所有参数(包括被this指针所指的哪个参数隐喻参数)进行类型转换,那么这个函数必须是个non-member.

注解:
       如果成员变量不是public,客户唯一能够访问对象的办法就是通过成员函数。如果public接口内的每样东西都是函数,客户就不需要在打算访问class成员时迷惑地试着记住是否使用小括号。如果你通过函数访问成员变量,日后可改以某个计算替换这个成员变量,而class客户一点也不会直到class地内部实现已经发生变化,这事封装地特性。如果你不隐藏成员变量,即使拥有class原始码,改变任何public事物地能力还是极端受到束缚,因为那会破坏太多客户码。Public意味着不封装,而不封装意味着不可改变,特别是堆被广泛使用地class而言。被广泛使用地class是最需要封装地一个族群,因为他们最能够从“改采用一个较佳实现版本”中获益
      某些东西的封装性与“当其内容改变的时候可造成的代码破坏量”成反比。假设我们有一个protected成员变量,当我们要最终取消它的时候,所有从它继承的派生类都会受到影响。
      protected成员变量就行public成员变量一样缺乏封装性,因为在这两种情况下,如果成员变量被改变,都会有不可预知的大量代码受到破坏。太多的代码需要重写、重新测试、重新编写文档、重新编译。
     从封装的角度来说其实只有两种访问权限:private(提供封装)和其他(不提供封装).

24.若所有参数皆需类型转换,轻为此采用non-member函数
     如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-memeber.
25.考虑写出一个不抛异常的swap函数
 当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常。
 如果你提供一个memeber swap,也应该提供一个non-member swap用来调用前者。对于class ,可以特化std::swap。
 为“用户类型”进行std templates 全特化是好的,但千万不要尝试在std内加入某些对std而言全是新的东西。
    调用swap时针对std::swap使用using声明式,然后调用swap并不带任何"命名空间资格修饰".
     
26.尽可能延后变量定义式地出现。这样做可增加程序的清晰度并改善程序的效率。
27.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。如果有个设计需要转型动作,试着发展无需转型的替代设计。
     如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用改函数,而不需将转型放进他们自己的代码内。
     宁可使用C++ style(新式)转型,不要使用旧式转型。前者很容易辨识出来,而且也比较有着分门别类的职掌。
28.避免返回handlers(包括references、指针、迭代器)指向对象内部。遵守这个条款可增加封装性,帮助const成员函数的行为像个const,并将发生”虚吊号码牌”的可能性降至最低。
29.异常安全函数(Exception-safe functions)即使发生异常不会泄漏资源或允许任何数据结构败坏。这样的函数区分为三种可能的保证:基本型、强烈型、不抛异常型。
     “强烈保证”往往能够以copy-and-swap实现出来,但”强烈保证”并非对所有函数都可实现或具备现实意义。
     函数提供的”异常安全保证"通常最高只等于其所调用之各个函数的”异常安全保证”中的最弱者。
注解:
        较少的代码就是好的代码,因为出错机会比较少,而且一旦有所改变,被误解的机会也比较少。
        基本型:如果异常被抛出,程序内的任何事物仍然保持在有效的状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。
        强烈型:如果常量被抛出,程序状态不改变。调用这样的函数需要这样的认知:如果函数成功,就是完全成功,如果函数失败,程序会回复到”调用函数之前”的状态。
        不抛异常型:承诺不抛出异常,因为它们总是能够完成它们原先的承诺。作用于内置类型身上的所有操作都提供nothrow保证。但是者很难满足,而合使用动态内存的东西如果无法找到足够内存以满足需求,通常便会抛出一个bad_alloc异常。对于大部分函数而言,抉择往往落在基本保证和强烈保证之间。

        以对象管理资源是良好的设计的根部。
        有一个一般化的设计很典型地会导致强烈保证,很值得熟悉它。这个策略被称为copy and swap.原则很简单:为你打算修改地对象(原件)做出一份副本,然后在那副本身上做一切必要地修改。若有任何修改动作抛出异常,原对象仍保持未改变状态。待所有改变都成功后,再将修改过地那个副本和原对象地一个不抛出异常地操作中置换 (swap)。

       如果系统内有一个(唯一一个)函数不具备异常安全性,整个系统就不具备异常安全性,因为调用那个函数可能导致资源泄漏或数据结构败坏。
        
       如何让自己撰写地代码更具安全性:1.以对象管理资源,那可阻止资源泄漏。2.挑选三个异常保证中地某一个实施于你所写地每一个函数身上。


个人特别喜欢书中最后的一段话:
     “四十年前,满载goto的代码被视为一种美好实践,而今天我们却致力于写出结构化控制流。二十年前,全局数据被视为一种美好的实践,而今我们却致力于数据的封装。十年前,撰写“未将异常考虑在内”的函数被视为一种美好的实践,而今我们致力于写出”异常安全的代码””.

30.将大多数inline限制在小型、被频繁调用的函数身上。这可使日后的调试过程和二进制升级更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。
      不要只因为function templates出现在头文件,就将它们声明为inline.
31. 支持"编译依存最小化”的一般构想是:相依于声明式,不要相依于定义式。给予此构想的两个手段是Handle classes和Interface classes.
     程序库头文件应该以"完全且仅有声明式”的形式存在。这种做法不论是否涉及templates都适用。
     
注解:
#include <string>
#include "date.h"
#include
 "address.h"

class Person
{
public:
    Person(
const std::string& name,const Date& birthday,const Address &addr);
    std::string name()
 const;
    std::string birthday()
 const;
    std::string address()
 const;
   
private:
    std::string theName;
    Date theBirthday;
    Address theAddress;
} 
       在编译 class person 需要包含string Date 和Address 类的相应的头文件,这样在Person定义文件和其含入文件之间形成了一种编译依存关系。如果这些头文件中有任何一个被修改,或这些文件所依赖的其他头文件有任何改变,那么每一个含入Person class的文件就得重新编译,任何使用Person class的文件也必须重新编译。这样的连串编译依存关系会对许多项目造成难以形容的灾难。
         可以使用两种方式来解除接口和实现之间的耦合关系:组合(Handle classes)和继承(Interface classes)

第一种方法
//Person.h
#include <string>
#include
 <memory>

class PersonImpl;
class Date;
class Address;

class Person
{
public:
    Person(
const std::string& name,const Date& birthday,const Address &addr);
    std::string name()
 const;
    std::string birthday()
 const;
    std::string address()
 const;
   
private:
    std::tr1::shared_ptr<PersonImpl> pImpl;
}

//Person.cpp
#include "Person.h"
#include
 "PersonImpl.h"

Person::Person(
const std::string& name,const Date& birthday,const Address &addr)
:pImpl(
new PersonImpl(name,birthday,addr))
{
}
std::string Person::name()
 const
{
   
 return pImpl->name();
}
        在上面的代码中,Person类内含一个指针成员,指向其实现类,这种设计叫“Pointer to implementation”。在这样的设计下,Person的客户就完全与Dates,Address以及Person的实现细目分离了,那些classes的任何实现修改都不需要Person客户端重新编译。此外由于客户无法看到Person的实现细目,也就不可能写出什么”取决于那些细节“的代码。这真正是”接口和实现分离”!
         这种分离的关键在于以”声明的依存性“替换”定义的依存性“,这正是编译依存性最小化的本质:现实中让头文件尽可能自我满足,万一做不到,则让它与其他文件的声明式(而非定义式)相依。可以使用如下的一些策略达到这样的目的:
 1.如果使用object reference或object pointerrs可以完成的任务,就不要使用objects
 2.如果能够,尽量以class声明式替换class定义式。
   注意:当你声明一个函数而它用到某个class时,你并不需要该class的定义;纵使函数以by value的方式传递该类型的参数(或返回值)。但是一旦任何人调用那些函数,调用之前Date定义式一定得先曝光才行。


第二种方法
#include <string>
#include
 <memory>

class PersonImpl;
class Date;
class Address;

class Person
{
public:
   
 static std::str1::shared_ptr<Person> create(const std::string& name,
                                               
 const Date& birthday,
                                               
 const Address& addr);
   
 virtual std::string name() const    = 0;
   
 virtual std::string birthday() const = 0;
   
 virtual std::string address() const  = 0;
   
 virtual ~Person();
};
class RealPerson:public Person
{
public:
    RealPerson(
const std::string& name,const Date& birthday,const Address &addr)
    :theName(name),theBirthday(birthday),theAddress(addr)
    {
    }
    std::string name()
 const;
    std::string birthday()
 const;
    std::string address()
 const;
   
 virtual ~Person();
private:
    std::string theName;
    Date theBirthday;
    Address theAddress;
};
std::tr1::shared_ptr<Person> Person::create(
const std::string& name,
                                           
 const Date& birthday,
                                           
 const Address& addr)
{
   
 return std::tr1::shared_ptr<Person>(new RealPerson(name,birthday,addr));
}
//客户端使用
std::string name;
Date dateOfBirth;
Address address;

std::tr1::shared_ptr<Person> pp(Person::create(name,dateOfBirth,address));
std::cout << pp->name()
          << pp->birthday()
          << pp->address();

Effective C++ 条款01:视 C++ 为一个语言联邦 这篇文章摘要: C++是一个由多个次语言组成的语言联邦,包括C风格过程式编程、面向对象的C++、模板元编程和STL标准库。作者通过《Effective C++》第一条指出,理解这种联邦结构是掌握C++的关键。文章详细解析了这四大次语言的核心特性和适用场景:C语言基础用于系统编程;面向对象特性适合大型架构;模板编程支持泛型和元编程;STL提供了容器和算法的高效实现。不同次语言的编程规则差异很大,混合使用时需要注意风格统一。文章通过嵌入式系统、游戏引擎等实际案例,展示了如何根据不同需求选择合适的次语言组合。理解 阅读详情

相关推荐

TSMaster如何用珠海创芯CAN卡实现高效CAN通信(附完整驱动安装指南)

本文详细介绍了如何使用TSMaster软件与珠海创芯CAN卡实现高效CAN通信,包括驱动安装、系统配置、ControlCAN.dll替换及TSMaster集成配置等关键步骤。通过实战指南和故障排除技巧,帮助工程师快速搭建稳定可靠的CAN通信测试环境,适用于汽车电子和工业控制等领域。

weixin_29201859的博客 481

【Effective C++】第五章 实现(上)

第五章 实现条款26:尽可能延后变量定义式的出现时间只要你定义了一个变量而其类型带有一个构造函数或析构函数,那么当程序的控制流到达这个变量定义式时,你便得承受构造成本;当这个变量离开其作用域时,你便得承受析构成本。即使这个变量最终并为被使用,仍需耗费这些成本,所以应该尽量避免这种情形。 考虑下面这个函数,它计算同学密码的加密版本后而返回,前提是密码够长。如果密码短,函数会丢出一个异常,类型为log...

stt2019 274

vasp计算练习1-Si

si的vasp训练流程

qq_41074165的博客 3296

Effective C++(条款26-31)

一、尽可能延后变量定义式的出现时间std::string encryptPassword(const std::string& password) { ... //可能抛出异常的部分,比如长度的检查 std::string encrypted(password); //通过复制构造函数

nawuyao的博客 883

VHDL按键消抖(状态机版本)

检测下降沿:设置一个和,分别代表之前的之前和之前的信号状态,若两个信号key_in_d2=1,key_in_d1=0,他俩的not key_in_d2 and key_in_d1为1,则说明下降沿产生,把它设置为标志位key_flag。延时计数:50MHz的板子每次计数需要20ns,而抖动时间大约为5-10ms。所以取7ms,作为延时时间。可以看见当检测到下降沿时,开始计数计数计满再次检测,若为低电平则为按下按键,否则为抖动。通过检测下降沿来临,延时计数再次检测,如果为低电平则为按键按下。

qq_69639216的博客 1084

多跳问答技术解析:从原理到金融领域实践

多跳问答(Multi-hop QA)是自然语言处理中的高级任务,要求系统通过多步推理整合分散信息来回答问题。其核心技术在于理解文档间的复杂关联,相比单跳问答需要更精细的数据集设计和模型架构。在金融、医疗等专业领域,多跳问答能有效处理如'腾讯大股东投资的港股上市公司'这类需要串联多个信息点的问题。典型实现方案包括MR-Search框架的三级检索器设计,分别处理实体召回、关系匹配和数值比较。当前最佳实践表明,结合稠密检索与稀疏检索的混合策略,配合动态路由机制,能在保持较高精度的同时控制计算成本。这类技术在金融风

weixin_42566072的博客 606

《Effective C++(第三版)》读书笔记

结合《Effective C++(第三版)》书和一些技术博客总结的读书笔记,后续还会更新完善 一.让自己习惯C++ 条款01:视C++为一个语言联邦     为了更好的理解C++,我们将C++分解为四个主要次语言: C。说到底C++仍是以C为基础。区块,语句,预处理器,内置数据类型,数组,指针统统来自C。 Object-Oreinted C++。这一部分是面向对象设计之古典守

liaodong1790的博客 841

DeepSeek 赋能智慧消防:以 AI 之力筑牢城市安全 “防火墙”

在数字化浪潮下,智慧消防系统亟需先进技术提升效能。DeepSeek 凭借 Transformer 架构与混合专家架构等核心技术,具备强大的多模态数据处理与智能决策能力,且支持本地化部署,保障数据安全。其在智慧消防领域的应用成效显著,从实现火灾风险动态感知与早期精准预警,到优化智能接警调度、设备健康管理,再到辅助应急指挥与疏散,有效降低火灾风险与事故损失。未来,DeepSeek 有望在智慧消防领域持续拓展,同时也需应对技术、数据等多方面挑战。

邓邓子的博客 1690

Effective C++读书笔记(上)

Effective C++读书笔记(一到三章)

still_wtm的博客 748

一文吃透 Tools for Applying SAP Notes:从 SNOTE、TCI 到 Solution Manager 与 SAP Cloud ALM

本文系统梳理了SAP技术与运维团队应用SAP Notes的高效工具与方法,涵盖On-Premise与云环境。文章首先阐述了精研SAP Notes工具的必要性,指出其是实施错误修复、法务变更和性能改进的关键载体。随后详细介绍了SNOTE、TCI、Solution Manager、Cloud ALM和Maintenance Planner等核心工具的定位与适用场景,并通过采购异常案例展示了标准更正流程。针对复杂修复场景,文章提出了TCI的批量处理方案,并强调将Note实施纳入变更治理流程的重要性。最后总结了三种

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 354

高通平台开发系列讲解(USB篇)MBIM协议详解

📢本文主要介绍高通平台USB网卡MBIM协议。

内核笔记 5438

Effective C++(第三版)读书笔记

Effective C++(第三版)读书笔记 文章目录Effective C++(第三版)读书笔记1. 让自己习惯C++01.视C++为一个语言城邦02. 尽量以const, enum, inline 替换 #define03. 尽可能使用const04. 确定对象被使用前已经被初始化2. 构造、析构、赋值运算05. 了解C++默默编写并调用哪些函数06. 若不想使用编译器自动生成的函数,就该明确...

Luven777的博客 392

基于YOLOv5s的RK3588多线程部署16FPS暴涨到120FPS 轻量化深度学习部署实战教程(包括性能优化与加速)37

本文介绍了如何在RK3588平台上利用线程池优化YOLOv5模型的推理性能。RK3588内置3个NPU核心,支持多核并行处理。作者设计了一个线程池架构:1个线程负责数据读取,10个线程处理NPU运算,1个线程输出结果。该架构包含任务队列、线程管理和工作线程三个核心组件,通过合理设置线程数、任务队列大小等参数确保性能稳定。文章提供了详细的C++实现代码,包括线程池初始化、任务提交、结果获取等功能模块,并讨论了多线程同步和内存管理的关键技术要点。该方案可显著提升深度学习模型在嵌入式设备上的部署效率。

FJN110的博客 9230

【读书笔记】Effective C++-1 让自己习惯C++(之一)

Effective C++读书笔记 --By Nathan.Yu 2007-11-10-- 1 让自己习惯C++ 条款01:视C++为一个语言联邦 C++最初的名称是:C with Classes 今天的C++是:多重泛型编程语言(multiparadigm programming language),同时支持过程形式(procedural)、面向对象形式(object-orie

@塘外人 882

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【读书笔记】Effective C++(01)让自己习惯C++

Effective C++ 读书笔记

LogM的博客 211

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

读书笔记-Effective C++

页数:47 条款一: 把C++视为一种联邦语言,因为支持,过程,面向对象,函数,泛型,元编程。 C语言的次语言,有C,Object-Oriented C++。这部分也就是C with Classes;Template C++(泛型编程,一般经验较少);STL 条款二:尽量用const,enum,inline替换define 要是出错,编译器只会定位define替换的东西,不方便找问题。用

baidu_34674626的博客 606

IEM模型,地表粗糙度模拟

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

【读书笔记】Effective C++-1 让自己习惯C++(之三)

Effective C++读书笔记 --By Nathan.Yu 2007-11-12-- 1 让自己习惯C++(三) 条款04:确定对象被使用前已先被初始化 读取未初始化的值会导致不明确的行为。 最佳的处理方法:永远在使用对象之前先将它初始化。        对内置类型:手工初始化。        对自定义类型:确保每个构造函数都将对象的每一个成员初始化。   别混淆了赋值

@塘外人 691

《Effective C++》读书笔记(一):让自己习惯C++(条款01~04)

读《Effective C++》第一章:让自己习惯C++ 而写的总结笔记,从条款01到条款04.

wjmhlh的博客 504

【读书笔记】Effective C++(05)实现

Effective C++ 读书笔记

LogM的博客 168

Effective C++(2)读书笔记

(1)为内置对象手工初始化,因为C++不保证一定会初始化它们 (2)为免除“跨编译单元之初始化次序”问题,用local static 对象替换non-local static对象         non-local static对象初始化次序无法确定,如果在未初始化以前调用就会产生大问题         extern FileSyatem tfs;         替换为        

rhythmhui1的专栏 431

《Effective C++》读书笔记第一章——让自己习惯C++(Accustoming Yourself to C++)

条款01:视C++为一个语言联邦 (View C++ as a federation of languages.) 与C++相关的四个特征: C. 说到底C++还是以C为基础。区块(blocks)、语句(statements)、预处理器(preprocessor)、内置数据类型(built-in data types)、数组(arrays)、指针(pointers)等统统来自C。然而C语言拥...

哈哈哈哈嘿嘿嘿 272

Effective C++ 读书笔记 (1.让自己习惯C++)

条款一: 视C++为一个语言联邦 将C++视为一个语言联邦,而非单一的语言,为了理解C++,必须认识四个主要的次语言: C Object-Oriented C++ (相当于是面向对象的C++) Templata C++ (C++泛型编程) STL C++并不是一个带有一组守则的一体语言;它是从四个次语言组成的联邦政府,每个次语言都有自己的规约。 C++高效编程守则视状况而变...

weixin_43133795的博客 167

【读书笔记】Effective C++-1 让自己习惯C++(之二)

Effective C++读书笔记 --By Nathan.Yu 2007-11-11-- 1 让自己习惯C++(二) 条款03:尽可能使用const const允许你指定一个语义约束(也就是指定一个“不该被改动”的对象),而编译器会强制实施这项约束。   const的用处:修饰global或namespace作用域中的常量;或修饰文件、函数、或区块作用域中被声明为static的对象;

@塘外人 744

effective c++_Effective C++ 读书笔记

作者:maxkibble链接:https://www.jianshu.com/p/67d2b4e2d417手头上有一本 Scott Meyes 的 Effective C++(3rd Edition)https://www.amazon.com/gp/product/0321334876,虽然中文的出版时间是感人的2011年(也就是说C++11的那些新特性都没讨论了),但看网上的一些评论...

weixin_39754831的博客 104

Effective C++(读书笔记)

Effective C++ 这本书共有九个章节55条建议,目录如下: 一. 让自己习惯C++       01.视C++为一个语言联邦       02.尽量以const, enum, inline, 替换#define       03.尽可能使用const       04.确定对象被使用前已被初始化 二. 构造/析构/赋值运算       05.了解C++默认编写并调用哪些函数...

前路漫漫的博客 490

C++ 读书笔记 Effective C++(三)

public继承意味着is-a;virtual函数意味着接口必须被继承 none-virtual函数意味着接口和实现都必须被继承。 32.确定你的public继承塑模出is-a关系        “public继承”意味is-a.适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象

zzbjut 2276
上一篇: 数据加密类型
下一篇: C++ 读书笔记 Effective C++(三)
张哲BJUT
博客等级 码龄15年 151粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值