《effective c++》读书笔记3

2024-06-13 01:58
文章标签 c++ 读书笔记 effective

本文主要是介绍《effective c++》读书笔记3,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

条款26:尽可能延后变量定义式的出现时间

std::string encryptPassword(conststd::string &password)

{

std::string encrypted;

encrypted=password;

encrypt(encrypted);

return encrypted;

}

这样定义即初始化encrypted付出的代价是一个构造函数和一个赋值函数。如果改用以下方式:

std::string encryptPassword(conststd::string & password)

{

std::string encrypted(password);

encrypt(encrypted);

return encrypted;

}

尽可能延后变量的定义,不仅能避免构造非必要对象,还可以避免无意义的默认构造行为。

n  尽可能延后变量定义式的出现。这样做可以增加程序的清晰度并改善程序效率。

条款27:尽量少做转型动作

n  如果可能,尽量避免转型,特别是在注重效率的代码中避免dynamic_cast。如果有个设计需要转型动作,试着发展无需转型的替代设计。

n  如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需要将转型放进他们自己的代码内。

n  宁可使用C++的新式转型,不要使用旧式转换。前者很容易辨识出来,而且也比较有着分门别类的职掌。

条款28:避免返回handles指向对象内部成分

考虑如下类的定义:

class GUIObject{…}

const Rectangle boundingBox(const GUIObject&obj);

客户有可能这么使用这个函数:

GUIObject *pgo;

const Point *pUpperLeft=&(boundingBox(*pgo).upperLeft());

上述的代码赋值号右边返回的临时的temp对象,然后temp对象会被释放,这是pUpperLeft会变成悬垂的(dangling)!

 n  避免返回handles指向对象内部,遵守这个条款可增加封装性,帮助const成员函数的行为像个const,并将发生dangling handles的可能性降到最低。

条款29:为异常安全而努力是值得的

异常安全函数提供三个保证之一:

基本保证:如果异常被抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或者数据结构会因此而破坏。

强烈保证:如果异常被抛出,程序状态不改变,调用这样的函数需有这样的认知:如果函数成功,就是完全成功,如果函数失败,程序会回复到调用函数之前的状态。

不抛出保证:承诺绝不抛出异常,因为它们总是能够完成它们原先承诺的功能。作用于内置类型身上的所有操作都提供不抛出保证。

条款30:透彻了解inlining的里里外外

将大多数inlining限制在小型被频繁调用的函数身上,这可使日后的调试过程和二进制升级更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。

不要只因为函数模板出现在头文件,就将它们声明为inline.

 条款31:将文件间的编译依存关系降到最低

n  如果使用对象的引用或者指针可以完成任务,就不要使用对象

n  如果能够,尽量以class声明代替class定义式

n  为声明和定义式提供不同的头文件

 条款32:确定你的public继承塑模出is-a关系

public继承意味着is-a,适用于baseclasses身上的每一件事情一定也适用于derived classess身上,因为每一个derived class对象也是一个base对象。

 条款33:避免遮掩继承而来的名称

n  派生类内的名称会遮掩基类内的名称,在Public继承下从来没有人希望如此。

n  为了让被遮掩的名称再见天日,可使用using声明或转交函数。

条款34:区分接口继承和实现继承

n  接口继承和实现继承不同,在Public继承之下,派生类总是继承基类的接口。

n  纯虚函数只具体指定接口继承

n  非纯虚函数具体指定接口继承及缺省实现继承。

n  非虚函数具体指定接口继承以及强制性实现继承

条款35:考虑虚函数以外的其它选择

条款36:绝不重新定义继承而来的非虚函数

public继承下,使用与基类对象的每一件事,也适用于派生类对象,因为每个派生类对象都是一个基类对象,派生类一定会继承非虚函数的接口和实现

条款37:绝不重新定义继承而来的缺省参数值

考虑以下类:

class Shape

{

public:

         enumShapeColor{Red,Green,Blue};

         virtualvoid draw(ShapeColor color=Red) const =0;

};

class Rectangle:public Shape

{

public:

         virtualvoid draw(ShapeColor color=Green) const;

};

如果定义以下变量:

Shape *p=new Rectangle;

p->draw(); //这一行实际调用的是Rectangle::draw(Shape::Red)

 virtual函数是动态绑定,而缺省参数值却是静态绑定,意思是你可能在调用一个定义于派生类内的虚函数的同时,却使用基类为它所指定的缺省参数值。

 条款38:通过复合塑模出has-a或者根据某物实现出

考虑实现一个set容器,假如使用链表,可以定义类如下:

class set

{

public:

         voidinsert(const T& item);

         voidremove(const T&item);

         …..

private:

         std::list<T>rep;

};

 这里set和list即为has-a关系。

n  复合的意义和public继承完全不同。

n  在应用域,复合意味着has-a。在实现域,复合意味着根据某物实现出。

条款39:明智而审慎地使用private继承

考虑一个空白类:

class Empty{};

class HoldsAnInt

{

private:

         intx;

         Emptye;

};

这时sizeof(HoldsAnInt)>sizeof(int);因为空类的对象e也会占据内存大小。

使用下面的替代实现:

class HoldsAnInt:private Empty

{

private:

         intx;

};

这时sizeof(HoldsAnInt)==4;

private 继承,使得空白基类最优化,缩小了派生类对象的大小。

n  private继承意味着根据某物实现出。

n  和复合不同,Private继承可以造成空的基类最优化,这对致力于对象尺寸最小化的程序库开发者而言,可能很重要。

条款40:明智而审慎地使用多重继承

使用virtual继承的那些类所产生的对象往往比使用非虚继承的兄弟们体积大,访问虚基类的成员变量时,也比访问非虚基类的成员变量速度慢。种种细节因编译器不同而异,但基本重点很清楚,你得为虚继承付出代价。

 

 

这篇关于《effective c++》读书笔记3的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1055973

相关文章

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

C++归并排序代码实现示例代码

《C++归并排序代码实现示例代码》归并排序将待排序数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的子数组合并,得到排序后的数组,:本文主要介绍C++归并排序代码实现的相关资料,需要的... 目录1 算法核心思想2 代码实现3 算法时间复杂度1 算法核心思想归并排序是一种高效的排序方式,需要用

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么