Effective C++ 总结

effective c++ 和 more effective c++中知识点 尽可能使用 const在 C++ 编程中,尽可能使用。 阅读详情
1.尽量以const,enum,inline代替#define
reason:你所使用的名称可能并未进入记号表。
可以用const double AspectRation=1.635替换#define ASPECT_RATION 1.635


定义常量的char *based字符串如下:
const char * const authorName="Scott Meyers";
在C++中使用string比较合适:
const std::string authorName("Scott Meyers");




const可以成为类专属常量
class CostEstimate
{
private:
   static const double FudgeFactor; //常量声明
};
const double CostEstimate::FudgeFactor=1.35;//常量定义,初值初始化可以放在常量声明处。


如果你不想让别人获取一个指针或引用指向你的某个整数常量,enum可以帮助你实现这个约束。


template<typename T>inline void callWithMax(const T& a,const T& b)
{
f(a>b?a:b);
}
a.对于形似函数的宏,最好改用inline函数替换#define
b.对于单纯常量,最好以const对象或enums替换#define


2.尽可能的使用const


char greeting[]="Hello";
char *p=greeting; //non-const pointer,non-const data;
const char * p=greeting;//non-const pointer,const data;
char * const p=greeting;//const pointer,non-const data;
const char * const p=greeting; //const pointer,const data;


void f1(const Widget *pw);//f1获取一个指针,指向一个不变的Widget对象。f2也是,两者写法一样。
void f2(Widget const *pw);


STL迭代器的作用就像是T *指针,声明迭代器为const就像声明指针为const一样(T *const指针),表示迭代器不能指向不同的东西,但他所指的东西的值可以改变。const T *相当于const_iterator;


const可以让函数返回一个常量值,可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。


const Rational operation*(cont Rational &lhs,const Ration &rhs);
如果不这样做,客户可能会写成(a*b)=c;,加上const可以预防没有意思的赋值动作。


const成员函数:使class接口比较容易理解,使“操作cosnt对象”称为可能。


两个成员函数如果只是常量性的不同,可以被重载。
const char& operator[](std::size_t position)const     //操作const对象
{
return text[position];
}
char & operator[](std::size_t position) //操作non-const对象
{
return text[position];
}




TextBlock tb("Hello");
cosnt TextBlock ctb("World");
std::cout<<tb[0];
tb[0]='x'; //返回值要是char的引用,要不然就不能赋值
std::cout<<ctb[0];
ctb[0]='x';//错误,写一个const对象。






const成员函数不能修改non-static的成员变量,如果要修改,要在声明成员变量前加mutable关键字。


运用const成员函数实现其non-const函数需要运用const_cast和static_cast转换,这样可以避免代码重复。
calss TextBlock
{
public:
const char &operator[](std:size_t position)const
{
...
...
return text[position];
}


char &operator[](std::size_t position) //调用const版本
{
reutrn const_cast<char &)(static_cast<const TextBlock &>(*this)[position]);
}
};


static_const将non-const对象转换成const对象,const_cast从返回值中移除const.




3.确定对象被使用前已被初始化


对于内置类型以外的东西,初始化的责任在构造函数上。




初始化与赋值是不同的,赋值最好用下面的方式写:
ABEntry::ABEntry(string &name,string &address):theName(name),theAddress(address)
{
//什么也不做
}
与放在函数体里面的最终结果一样,但是上面的方法效率高。


4.了解C++默认编写并调用哪些函数


如果写下:
class Empty{};
编译器会生成默认的构造函数,copy构造函数,赋值操作符
class Empty
{
 public:
   Empty(){}   //默认的构造函数
   Empty(const Empty &rhs){}
   ~Empty(){}
  Empty & operator=(const Empty &rhs){} 
}


如果一个类含有引用成员,必须自己定义copy assignment操作符。




5.若不想使用编译器自动生成的函数,就应该明确拒绝




class HomeForSale
{
public:
 private:
 HomeForSale(const HomeForSale&); //不实现
 HomeForSale& operator=(const HomeForSale&);//防止编译器自动生成copy构造函数和赋值操作符,这样防止用户调用


}


6.为多态基类声明virtual析构函数。


不加virtual可能导致局部销毁对象。任何的类只要带有virtual函数都几乎要一个virtual虚函数。


可以将析构函数定义为纯虚析构函数,但是要为纯虚析构函数提供一份定义,因为析构函数是先调用最深层派生的那个类的析构函数,然后是每一个基类的析构函数。
所以必须为纯虚析构函数一个定义。
class AWOV
{
public:
virtual ~AWOV()=0;
}
AWOV::~AWOV(){} //提供定义
将析构函数定义为虚函数只针对要提供多态性的基类定义。




7.别让异常逃离析构函数
析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常。


8.绝不在构造函数和析构函数中调用virtual函数




9.令operator=返回一个reference to *this


int x,y,z;
x=y=z=15;
为了实现“连锁赋值”,赋值操作符必须返回一个reference指向操作符的左侧实参。
class Widget
{
public:
Widget& operator=(const Widget& rhs)
{
return *this; //指向当前对象


}
}


10.在operator=中处理“自我赋值”


自我赋值检验:
class Bitmap{};
class Widget
{
private:
Bitmap *pb; //指针,指向一个从heap分配而得到的对象
}
Widget& Widget::operator=(const Widget &rhs)
{
if(this==&rhs) return *this;  //如果是自我赋值,就不做任何事


delete pb;
pb=new Bitmap(*rhs.pb);
return *this;
}
或者用下面:
Widget& Widget::operator=(const Widget &rhs)
{
Bitmap *pOrig=pb;  //记住原先的pb
pb=new Bitmap(*rhs.pb); //令pb指向*pb的一个复件
delete pOrig;  //删除原来的pb
return *this;
}




11.在继承当中,子类复制对象时别忘记每一个成分即父类


如:
class Date{};
class Customer
{
public:
private:
std::sgring name;
Date lastTransaction;
};


class PriorityCustomer:public Customer
{
public:
PriorityCustomer(const PriorityCustomer &rhs);
PriorityCustomer & operator=(const PriorityCustomer& rhs);
private:
int priority;


};


PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)      //调用基类的复制构造函数
{
logCall("PriorityCustomer copy constructor");
}


PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer copy  assignment operator");
Customer::operator=(rhs); //对基类成分进行赋值动作
prority=rhs.priority;
return *this;
}




-----------------------------------------资源管理--------------------------------------


12.以对象管理资源
class Investment{};
Investment *createInvestment(); //工厂方法


void f()
{
Investment *pInv=createInvestment();


...
delete pInv;//释放pInv所指的对象,但是这个存在潜在的资源泄露的可能性
}


可以使用auto_ptr来避免
void f()
{
std::auto_ptr<Investment> pInv(createInvestment());
//由auto_ptr的析构函数自动删除pInv
}
对于动态分配的数组不要使用该方法。




13.成对使用new和delete时要采取相同的形式
不要对数组形式做typedef动作
std::string * ptr1=new std::string;
std:string *ptr2=new std::string[100];
delete ptr1;
delete [] ptr2;//删除是由对象组成的数组




14.以独立的语句将newed对象放入只能指针
processWidget(std::auto_ptr<Widget>(new Widget),priority());
上面应该分开写:
a. std::auto_ptr<Widget> pw(new Widget);
b.processWidget(pw,priority());




-----------------------------------------设计与声明--------------------------------------
15.用const的引用传递参数去替代按值传参数
这样可以更高效,可以避免切割问题,该规则不适合内置类型以及STL的迭代器和函数对象。


16.当函数必须返回对象时,不要返回其引用


const Rational & operator*(const Rational &lhs,const Rational &rhs)
{
Rational *result=new Rational(lhs.n*rhs.n,lhs.d*rhs.d);//on-the-heap
return *result;
}
//上面的写法无法完成delete调用,导致资源泄露
“必须返回对象”的正确写法:
inline const Rational  operator*(const Rational &lhs,const Rational &rhs)
{
 return  Rational(lhs.n*rhs.n,lhs.d*rhs.d);  


}
绝对不要返回pointer或reference指向一个local stack对象,或返回指向一个heap-allocated对象或返回pointer或local static对象而有可能同时需要多个这样的对象。




17.将成员变量声明为private,protected并不比public更具有封装性。


18.若所有的参数皆需类型转换,请采用非成员函数


例如运算符*的重载:
class Ration
{
public:
const Rational operator*(const Rational &rhs)const;




};


混合式算术:result=oneHalf*2;//正确
              result=2*oneHalf;//错误,不能隐式转换


应该采用非成员函数
class Rational{....};


const Rational operator*(const Rational &lhs,const Rational&rhs)  //若不是采用Rational的成员函数,需要将这个函数声明为Rational的friend...
{
return Rational(lhs.n*rhs.n,lhs.d*rhs.d);
}
Rational oneFourth(1,4);
Rational result;
result=oneFourth*2;
result=2*oneFourth; //现在两个都可以
如果需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个非成员函数。






----------------------------------------- 实现--------------------------------------
19.尽量少做转型


C++提供的新式转型
 const_cast<T>(expression)  //通常用来将对象的常量性转除
dynamic_cast<T>(expression)  //用来决定某对象是否归属继承体系中的某个类型
reinterpret_cast<T>(expression)
static_cast<T>(expression) //强迫隐式转换,例如将non-const对象转换为const对象


20.避免返回handles指向对象内部成分


class Rectangle
{
public:
  const Point& upperLeft() const{return pData->ulhc;}  //第一个const不能丢掉,要不然客户就可以修改Point内部数据,破坏封装性
}


21.将文件的编译依存关系降至最低
尽量以class的声明式替换class的定义式










----------------------------------------- 继承与面向对象设计-------------------------------------
22.确定你的public继承塑模出is-a的关系


23.避免遮掩继承而来的名称


class Base
{
private:
int x;
pubilc:
virtual void mf1()=0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};


class Derived:public Base
{
public:
virtual void mf1();
void mf3();
void mf4();
};


调用:Derived d;
int x;
d.mf1(); //正确,调用Derived::mf1();
d.mf1(x);//错误,因为Derived:mf1遮掩了Base:mf1
d.mf2();//正确,调用Base::mf2();
d.mf3();//正确,调用Derived::mf3();
d.mf3(x);//错误,因为Derived::mf3遮掩了Base::mf3


为了避免上面的遮掩,可以采用如下方式:


class Derived::public Base
{
public:
using Base::mf1; //让Base Class 内名为mf1和mf3的所有东西在Derived作用域内可见(并且public)
using Base::mf3;
virtual void mf1();
void mf3();
void mf4();
};




若不想继承Base 的所有函数,可以采用private继承
class Base
{
 public:
  virtual void mf1()=0;
virtual void mf1(int);
};
class Derived:private Base
{
public:
  virtual void mf1()
{
Base::mf1();
}
};


调用:
Derived d;
int x;
d.mf1();//调用Derived:mf1
d.mf1(x);//错误,Base::mf1()被遮掩了


24.区分接口继承和实现继承


a.声明一个纯虚函数的目的是为了让子类只继承函数接口。
b.声明一个虚函数的目的是让子类继承该函数的接口和缺省实现。
c.声明一个非虚函数的目的是为了让子类继承函数的接口及一份强制性实现。
25.绝不重新定义继承而来的非虚函数


26.绝不重新定义继承而来的缺省参数值


class Shape
{
public:
  enum ShapeColor{Red,Green,Blue};
void draw(ShapeColor color=Red)const
{
doDraw(color); //调用一个虚函数
}
private:
 virtual void doDraw(ShapeColor color) const=0;
};


class Rectangle:public Shape
{
public:
  private:
  virtual void doDraw(Shape color)const; //不需要指定缺省参数值,已继承
};




27.通过复合塑模出has-a的关系
这样可以保证子类的的默认参数会一致,因为缺省参数值是静态绑定。
[Effective modern cpp]现代c++区别 读书笔记创建对象时使用()和{}的区别空指针优先选用nullptr,而非0或null 创建对象时使用()和{}的区别 1、大括号可以指定容器的初始内容&amp;gt;。 std::vector&amp;lt;int&amp;gt; v{1,3,5} 2、大括号可以用来为非静态成员指定默认初始化值,也可以用’='的初始化语法,不能用()。 class Widget{ ... private: int x{0};/... 阅读详情

相关推荐

Effective Modern C++ Scott Meyers 类型推导 Type Deduction 《Effective STL》 vector and string

Effective Modern C++》是一本由Scott Meyers撰写的书籍,该书主要讨论了C++11和C++14(现代C++)中的关键特性和最佳实践,以帮助读者编写出更高效、更安全、更易维护的代码。Scott Meyers是世界顶级的C++软件开发技术权威之一,他曾是C++ Report的专栏作家,并为C/C++ Users Journal和Dr. Dobb’s Journal等刊物撰稿。

万有文的博客 2301

Effective-Modern-Cpp 项目常见问题解决方案

Effective-Modern-Cpp 项目常见问题解决方案 项目基础介绍 Effective-Modern-Cpp 是一个开源项目,旨在提供 C++11 及其之后标准的最佳实践。该项目适合希望快速入门现代 C++ 的开发者,特别是那些已经掌握 C++ 基础语法和 C++98 最佳实践的开发者。项目主要使用 C++ 编程语言,包含了一系列关于现代 C++ 编程的最佳实践和技巧。 主要编程语言 ...

gitblog_00864的博客 444

Nginx反向代理MinIO私有桶签名失效?一招解决Host头校验问题

本文详细解析了Nginx反向代理MinIO私有桶时出现的签名失效问题,重点解决了Host头校验导致的"SignatureDoesNotMatch"错误。通过精准配置proxy_set_header保持Host头一致性,并提供了二级目录代理和调试指南,帮助开发者高效解决这一常见技术难题。

weixin_29201313的博客 320

Effective-Modern-CPP 开源项目指南

Effective-Modern-CPP 开源项目指南 项目概述 本指南旨在帮助开发者快速理解和上手 Effective-Modern-C++ 这一开源项目。该项目基于Scott Meyers的同名书籍《Effective Modern C++》,旨在通过代码示例展示C++11及以后版本中的现代编程实践和技术。 1. 项目目录结构及介绍 ├── README.md # 项目说明文件,包...

gitblog_00774的博客 472

【软件安装系列】Ubuntu+mysql5.7.27+Jira8.3.1+邮箱服务器配置+Confluence6.15.7安装经验和采坑总结

文章目录一、软件准备(百度云易被吞,就不放了)1.1 官网下载的新鲜的Jira和Confluence1.2 linux的jdk一份1.3 Jira和Confluence的破解程序或者破解包一份1.4 java的连接器一份二、安装过程1--java环境配置2.1 将下载下来的jdk包解压在/usr/local/java目录中2.2 写入环境变量三、安装过程2--mysql5.7.27环境配置3.1 ...

xiaosha_的博客 6890

DSP28335新手避坑指南:手把手教你用CCS6.2生成10KHz SPWM(附完整工程)

本文详细介绍了如何使用DSP28335开发板和CCS6.2环境生成10KHz SPWM波形的完整工程指南。从开发环境配置、ePWM模块设置到SPWM算法实现,特别针对新手常见问题提供了解决方案和调试技巧,帮助工程师快速掌握DSP28335的SPWM生成技术。

weixin_42522374的博客 182

effective modern cpp

中文网页版 https://github.com/kelthuzadx/EffectiveModernCppChinese https://www.kancloud.cn/kangdandan/book/169968

janeqi1987的专栏 493

Ferry工单平台部署

ferry工单平台部署

运维求生之路 1897

【Cpp】《Effective C++》第一章-让自己习惯C++

  这是我在学习《Effective C++》中总结得出的心得与体会,完全是以我自己的理解所作的笔记,是对个人经验的积累。基于第三版我以每个章节进行总结,全书一共九个章节。 第一章-让自己习惯C++ 条款01:视C++为一个语言联邦   View C++ as a federation of languages.   在初期Cpp被开发之初,Cpp并没有如今这样丰富的功能,它更应该被称为仅是一个带...

qq_41669298的博客 340

计算机网络Wireshark实验(西安交通大学)

实验名称 计算机网络Wireshark实验 实验日期 2021 年 5 月 17 日 实验地点 XJTU

沉鱼叶的博客 1814

语义通信高斯信道仿真代码

【代码】语义通信高斯信道仿真代码。

一去不复返的通信er 427

Effective C++ 学习笔记

C++程序员分为两种,一种是读过Effective C++的,一种是没读过。这本《Effective C++》 能够协助成为高效的C++开发者。简直是C++开发者的分水岭。 必须细读多遍。 本人小硕菜鸡一枚,非科班,准备今年7月从事C++开发者,修炼内功,一天学习一个effective C++条款。欢迎大佬指导讨论。 fighting!

Ref.Ptr.的博客 3869

某程token参数逆向分析

作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!

weixin_73499887的博客 2882

Effective & More Effective C++总结

 一、说明。1、E指的是《Effective C++ 第二版》2、M指的是《More Effective C++ 第二版》二、总结1、如果需要定制自己的operator new(通常是在需要分配大量的小对象,而且对性能要求特别敏感的程序里),具体的使用准则请参看 E7/E8/E9/E10。     (1)、全局的operator new 在里定义,可以通过::operator

jimmy_cheung_jc的专栏 765

YOLOv9改进,YOLOv9添加CBAM注意力机制

CBAM是一个简单而有效的注意力模块,用于前馈卷积神经网络。给定一个中间特征图,我们的模块按顺序推断两个独立维度(通道和空间)的注意力图,然后将注意力图乘以输入特征图以进行自适应特征细化。由于 CBAM 是一个轻量级的通用模块,因此它可以无缝集成到任何 CNN 架构中,开销可以忽略不计,并且可以与基础 CNN 一起进行端到端训练。论文链接:(CBAM论文)

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 856

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

再读effective c++

现在所说effective C++的系列历史,最开始Meyers出版的是effective C++第一版,然后有了more effective C++,然后是effective C++的第二版,接着是effective C++的第三版,最后是最新的 effective modern C++。effective modern C++里主要讲C++ 11的现代编程语言特性,包括类型推导,移动语义,右值

zhouguoqionghai的博客 3239

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《effective C++》阅读笔记

《effective C++》阅读笔记

subtitle_的博客 1044

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Effective C++与More Effective C++全书签中英文版本

Effective C++与More Effective C++全书签中英文版本 去发现同类优质开源项目:https://gitcode.com/ 简介 本仓库提供了C++程序员必备的进阶学习资料——《Effective C++》和《More Effective C++》的中英文对照版本。压缩包内共计四本书籍,其中《Effective C++》中文版为高清影印版,其余三本均为文字版本,保证清晰度,...

gitblog_06722的博客 352

Effective C++和More Effective C++

More Effective C++读书笔记 条款1:指针与引用的区别 二者之间的区别是:在任何情况下都不能用指向空值的引用,而指针则可以;指针可以被重新赋值以指向另一个不同的对象,但是引用则总是指向在初始化时被指定的对象,以后不能改变 在以下情况下使用指针:一是存在不指向任何对象的可能性;二是需要能够在不同的时刻指向不同的对象 在以下情况使用引用:总是指向

clam_clam的专栏 6972

Effective Cpp 条例解析

Effective 条例解析Effective 条例解析 一 让自己习惯C 1 视C为一个语言联邦 2 尽量以constenuminline 替换define 3 尽可能使用const 4 确保对象在使用前已经被初始化 二构造析构赋值运算 1 了解C默默编写并调用哪些函数 2 如果不想使用编译器提供的函数应当明确拒绝 3 为多态基类声明virtual析构函数 4 别让异常逃离析构函数 5 绝不在构造

李兰溪的专栏 1012

Note Of Effective C++ 、More Effective C++ And Effective Modern C++

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 Note Of Effective C++ 、More Effective C++ And Effective Modern

weixin_41077017的博客 1717

CPP & 笔记 - More Effective C++

基础议题 Item M1:指针与引用的区别 指针 存在不指向任何对象的可能 需要能够在不同的时刻指向不同的对象 引用 必须指向一个对象,并且不想改变其指向 在重载操作符,并为防止不必要的语义误解时,如: char &operator[](size_t idx); Item M2:尽量使用 C++ 风格的类型转换 static_cast<type>(expression):用于变量类型转换 const_cast<type>(expression):用于转换表达

灰黑的博客 302

Effective_Modern_Cpp

摘自:https://www.kancloud.cn/kangdandan/book/169966

qq_40230900的博客 235

C++primer、Effective C++应该怎么读,如何读?

导读 刚开始C++的学习肯定就是拿起书就开始读,读了一会就放下就干别的,带最后没翻过几页。下面我就说一下,我是怎么读的,我大概一个暑假就把这两本读完了。 C++ primer 计划 有人听到计划可能退缩了,计划都是骗人的,都是假的。我的计划有点和别人不一样。听我细细道来。 首先我规定自己一天必须读完一章。这一章不管大小(当然后面的泛型或者虚函数的地方可以规定半章一天)。大家不用分的太细,几点到几点...

曲怪曲怪 1884

《C++ Primer》和《Effective C++》哪个更难?

维度学习曲线渐进平缓但周期长陡峭(依赖前置知识)难点类型知识广度 $\propto$ 记忆量理解深度 $\propto$ 经验积累典型挑战模板特化、移动语义异常安全、资源管理价值阶段语言入门 $\to$ 进阶规避陷阱 $\to$ 工业级代码建议:初学者建议先通读《C++ Primer》建立知识框架,再通过《Effective C++》深化实践认知。两本书配合使用效果最佳,前者解决"怎么做",后者解决"怎么做更好"。

2509_93016958的博客 520
上一篇: C/C++浮点数在内存中的存储方式
下一篇: 双向链表的相关操作C++实现
xiaoding133
博客等级 码龄19年 415粉丝 159原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值