Effective C++学习第一天

1:区分C++中的术语声明、定义、初始化的概念

         声明(declaration):告诉编译器某个东西的名称和类型,但略去其他细节(可以出现多次,编译器不分配内存)。

         定义(definition):提供编译器一些声明式所遗漏的细节,编译器此时为对象分配内存(注意内置类型和自定义类型定义的变量都叫做对象,变量有且仅有一次定义)。

         声明和定义:1)extern关键字区分;2)声明中出现初始化式,当做定义,即使出现extern关键字;3)带{ }的是定义,其他的是声明;

         引申:头文件中不要放入变量定义,容易导致重复定义错误;可以使用static关键字把变量定义限制在源文件作用域内;

头文件中一般不放实体定义,但有三个例外:const常量定义;类的定义;inline函数;

         如何区分声明和定义,可以参考这篇文章:https://blog.csdn.net/sjxbf/article/details/6310150;

         初始化(initialization):给予对象初值的过程;用户自定义函数对象初始化由构造函数执行,default构造函数可以调用不带任何实参(通常有两种情况:情况1:没有参数;情况2:每个参数都有缺省值)

2:explicit关键字:用来阻止执行隐式类型转换,但仍可以执行显示类型转换;  

         explicit主要用于单个参数的类构造函数中,如果出现多个参数,explicit关键字失效,除了一种情况例外,就是除了第一个参数,其他参数都有默认缺省值时,explicit依然有效;

3:copy构造函数和copy assignment操作符

         copy构造函数:用于同型对象初始化自我对象时(初始化);

         copy assignment操作符:用于从一个同型对象中拷贝其值到自我对象(赋值操作时);

        copy构造函数的几个运用场所:1)初始化时,如Wiget w2;Wiget w1(w2);2)初始化赋值时;Wiget w2=w1;3)类对象值传递的时候;

4:命名习惯:养成选用所实现目标的英文翻译是个不错的选择,可以方便阅读和修改;例如类中的左右操作数可以定义参数名称为lhs(left-hand-side)和rhs(right-hand-side);

5:合理利用TR1(class template和function template,hash table,reference-counting smart pointers,regular expressions)和boost网站资源(提供可移植,同僚复审,源码开发的C++程序库)

6:C++语言是一个多重范型编程语言(multiparadigm programming language),一个同时支持过程形式(procedural)、面向对象形式(object-oriented)、函数形式(functional)、泛型形式(generic)、元编程形式(metaprogramming)的语言。C++可以视为由相关语言组成的联邦和非单一语言,其中每个次语言中,各种守则与通例都倾向于简单直观易懂和容易记住,关键是次语言之间切换过程。次语言分为一下几个方面:

         1)C:区块(blocks),语句(statement)、预处理器(preprocessor)、内置数据类型(bulit-in data types)、数组(arrays)、指针(pointers),但在高效编程时C语言却没有C++的功能如模板(template)、异常(exceptions)、重载(overloading)等;

      2)object-oriented C++:classes(构造和析构函数)、封装(encapsulation)、继承(inheritance)、多态(polymorphism)、virtual函数(动态绑定);类的三个核心:封装,继承,多态;

          3)Template C++。C++泛型编程的思想;

         4)STL。STL是个template程序库,它将容器(containers)、迭代器(iterators)、算法(algorithm)以及函数对象(function objects)联合起来;

7:尽量使用const,enum,inline替代#define(用编译器替代预处理器)

       #define 是在程序预处理的时候执行的,它不被看成语言的一部分,也就可能会出现所使用的宏变量没有进入到记号表(symbol table)中,修改的方式:用一个常量替代宏;另外使用const还有一个好处,系统会做类型检查,同时完成类型的位数限制(发生在float中)如#define pi 3.141592653;和const float pi=3.141592653得到的结果不一样,相比之下,用const会产生更小量的码值;

    # define并不注重作用域(scope)的概念,一旦定义,除非#undef,后面都有效,因此不能用于定义类的专属常量,也不能提供任何封装性;但const却能提供这样的功能,const可以将常量的作用域限制在classes内,让它成为class的一个成员,为了确保常量最多有一份实体,你得设置为static成员,如:

 class gameplayer{

private:

          static const int Numturns=5;//常量声明式,和以往static声明和定义不一样,这种成为in-class初值设定                                                                           //只允许对整形变量使用,还和C++编译器是否支持有关

         //static const double score;一般的static常量声明

          int score[Numturns];//使用常量

};

const double gameplayer::score=95.0;//static常量定义

类中的Numturns是一个声明式而非定义式,C++要求你对你所使用的任何东西提供定义式,但如果它是类的一个专属常量而且还是整形类型(int,char,bool),则需要特殊处理。只要不取地址,可以直接声明并使用,不需要提供定义式;但如果你取了某个类专属常量的地址或者编译器需要看到一个定义式,则你必须提供定义式:const int gameplayer::Numturns;//声明时已经赋值,定义则不需要赋值(放入实现文件而非头文件中)

      如果编译器不允许static整数型class常量完成in-class初值设定,可以用the enum hack补偿方法完成同样功能;

 class gameplayer{

private:

          enum {Numturns=5};

          int score[Numturns];//使用常量

};

    引申:enum hack知识:enum hack的行为有点像#define而非const,因为其和#define同样不能取地址,而const可以,如果不想让别人获得一个指针或者引用指向你的某个常量,enum可以实现这个功能;此外,enum hack是template metaprogramming(模板元编程)的基础技术;

     #define常见的误用情况是用它实现宏(macros),宏看起来像函数,却不会招致函数调用带来的额外开销,这也是错误的根源,如:

     #define CALL_WITH_MAX(a,b)  f((a)>(b)?(a):(b))

     int a=5;b=0;CALL_WITH_MAX(++a,b);//a被累加两次   

     解决方案:使用template inline函数,会在被调用处代码展开,省去参数压栈、栈帧开辟和回收、结果返回;同时会做安全检查或者自动类型转换;

     inline void callwithmax(const int&a,const int&b){f(a>b?a:b);}

     结论:对于单纯变量,最好以const对象或者enum替换#define;

               对于函数的宏,最好改用inline函数替换#define;

8:尽量多使用const:它允许你指定一个语义约束,而编译器执行这个约束,它允许你告诉编译器和其他程序员某值应该保持不变;

     1)STL迭代器中:声明迭代器为const,则迭代器指针不能变化,声明迭代器内容为const,如const_iterator,则迭代器内容不可变;

    2)在函数声明式中,const可以和返回值、各参数、函数本身产生关联;令函数返回一个常量值,往往可以降低因用户错误而造成的意外,同时不放弃安全性和高效性,如无意中输入的if(a*b=c)操作,可通过返回值设为const来避免这个错误;

    3)const成员函数:设置成const好处(方便理解;使操作const对象成为可能,编程更加高效);如果两个成员函数只是常量(constness)不同,可以被重载,这是C++的一个特性;

      引申:如果函数返回值是一个内置类型,那么改动函数返回值是不合法的,C++以by value返回对象意味着改动的只是对象的一个副本,而不是本身,这并不是我们希望的,因此需要把其设置为引用;

     成员函数是const意味着什么?有两种说法:bitwise constness(physical constness)和logical constness;bitwise constness认为成员函数不改变对象中的任何成员变量的任何一个bit,因此编译器只需要寻找有无成员变量赋值操作,bitwise constness这一个特性是C++对常量性(constness)的定义,因此const成员函数不能改变对象中的任何non-static成员变量,但是在指针的作用下这个const会发生问题,如:

    const mystring a("hello world"); char *pc=&a[0];*pc='j';//改变了const特性

   logical constness:一个const成员函数可以修改它处理对象内的某些bits,但只有在客户端侦查不出的情况下才能如此,如何解除编译器中的bitwise constness特性呢?可以使用const相关的一个关键字mutable,mutable可以释放non-static成员变量中的bitwise constness约束;

 4)在const和non-const中避免重复的方法:用其中一个调用另外一个,通过我们采用常量性转移,如;

class textblock{

public:

      const char&operator[](std::size_t position)const     //const 成员函数不变

     {

     }

   char& operator[](std::size_t position)

   {

      return const_cast<char&>(//去除返回值const

            static_cast<const textblock&>(*this)//this指针添加const

              [position]);

   } 

};

    采用non-const调用const版本的函数来避免重复,而不是相反的做法,原因:const变为non-const过程中可能会使得const变量发生变化,这与我们预期不合;而non-const本身就是可变的,不用担心这个现象的发生;

结论:声明const可以帮助编译器侦查出错误的用法;

         编译器强制实行bitwise constness,但可以通过指针方式改变;

        const和non-const成员函数有着实质等价的实现时,可以用non-const调用const来避免代码重复;

    





         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis运维和开发学习笔记(1) Redis简介

文章目录Redis的特性速度快持久化多种数据结构主从复制高可用和分布式典型的应用场景Redis启动和可执行文件Redis可执行文件说明启动方式验证redisredis常用配置redis数据结构和内部编码Redis是单线程&#xff0c;不会同时执行两条命令哈希慢查询pipelineRedis的特性 速度快 …

Effective C++学习第二天

1&#xff1a;确保对象被使用前已先被初始化&#xff0c;读取未初始化的值会造成不明确的行为&#xff0c;可能导致程序终止运行或者其他不可预期的现象&#xff1b;在C中&#xff0c;当你使用C part of C(C中C语言部分的内容&#xff09;且初始化可能导致运行期成本&#xff0…

Redis运维和开发学习笔记(3)redis搭建集群

Redis运维和开发学习笔记(3)redis搭建集群 文章目录Redis运维和开发学习笔记(3)redis搭建集群Redis集群搭建Redis集群搭建 cp /etc/redis.d/redistest_7001.conf /etc/redis.d/redistest_XXXX.conf :%s/7001/xxxx/g 配置文件内容&#xff1a;cluster-enabled yes ############…

Effective C++学习第三天

1&#xff1a;为多态基类声明virtual析构函数当我们创建一个base class指针指向新生成的derived class时&#xff0c;当删除基类指针时&#xff0c;如果base class是一个non-virtual析构函数时&#xff0c;实际执行的结果通常是derived class中的base成分被销毁&#xff0c;der…

linux创建指定大小的文件

一、生成文件大小和实际占空间大小一样的文件 dd if/dev/zero ofname.file bs1M count1 文件名称name.file bs1M表示每一次读写1M数据&#xff0c;count50表示读写 50次&#xff0c;这样就指定了生成文件的大小为50M。 二、生成文件大小固定&#xff0c;但实际不占空间命令 …

Effective C++学习第四天

条款11&#xff1a;在operator中处理自我赋值的现象虽然我们在平时可能不会出现显示自我赋值的现象&#xff0c;当加入指针或者引用时&#xff0c;可能会出现不同的指针或引用指向同一对象&#xff08;对象的不同别名&#xff09;&#xff0c;这时候我们就得考虑对象是否是同一…

Effective C++学习第五天

条款14&#xff1a;在资源管理类中小心copy行为当我们深入理解“资源取得时机是初始化时机&#xff08;RAII&#xff09;”概念&#xff0c;并以此作为“资源管理类”的核心时&#xff0c;我们可能会遇到将RAII对象复制的情况&#xff0c;一般有两种情况处理这个现象&#xff1…

Redis运维和开发学习笔记(2) redis持久化

Redis运维和开发学习笔记(2) redis持久化 文章目录Redis运维和开发学习笔记(2) redis持久化持久化持久化方式一:RDB触发~~的三种~~方式1. save命令2. bgsave配置触发机制RDB 总结持久化方式二:AOFAOF的三种策略三种策略的优缺点AOF重写机制持久化 redis将所有数据保存在内存中&…

Effective C++学习第六天

条款18&#xff1a;让接口更容易被正确使用&#xff0c;不易被误用设计接口的原则&#xff1a;正确性、高效性、封装性、维护性、延展性以及协议的一致性&#xff1b;设计原则&#xff1a;1&#xff09;导入新类型来预防很多客户端的错误&#xff0c;多使用系统类型&#xff08…

Redis运维和开发学习笔记(4) Redis参数意义

Redis运维和开发学习笔记(4) Redis参数意义 文章目录Redis运维和开发学习笔记(4) Redis参数意义参数意义参数意义 Client连接 问题 id567800790 addr10.18.17.217:37310 fd1572 name age2039114 idle2034860 flagsN db0 sub0 psub0 multi-1 qbuf0 qbuf-free0 obl0 oll0 omem0 …

Effective C++学习第七天

条款23&#xff1a;宁以non-memeber、non-friend替换member函数non-member/non-friend可以给对象带来更大的封装性&#xff0c;从两个方面来考虑&#xff1a;1&#xff09;考虑封装&#xff0c;越多东西被封装&#xff0c;它们就越不可见&#xff0c;就越少人看到它&#xff0c…

Redis运维和开发学习笔记(5) 主从复制和sentinel哨兵模式

Redis运维和开发学习笔记(5) 主从复制和sentinel哨兵模式 主从复制 将主节点的数据改变同步给从节点 作用 备份数据读写分离 存在的问题&#xff1a; 手动干预切主等操作主节点的写能力受到单机限制主节点的存储能力受到单机限制 主从模式的故障恢复 当主节点发生故障时&am…

Effective C++学习第八天

条款26&#xff1a;尽可能延后变量定义式的出现时间当你定义了一个变量&#xff0c;如果在使用变量之前出现异常&#xff0c;那么你得承受一次构造成本和析构成本&#xff0c;而且你没有使用该变量&#xff1b;本条款给出的建议是延迟变量的定义&#xff0c;直到非得使用该变量…

Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令

Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令 文章目录Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令info serverinfo clientinfo memoryinfo persistenceinfo statsinfo commandstatsinfo cpuinfo clusterinfo keyspaceinfo server Redis服务器相关的通用…

Effective C++学习第九天

条款32&#xff1a;确定你的public继承塑模出is-a模型class D&#xff08;derived&#xff09;以public形式继承class B&#xff08;base&#xff09;&#xff0c;则每一个类型为D的对象同时也是一个类型为B的对象&#xff0c;反之不成立&#xff0c;因此B比D表现出更加一般化的…

Effective C++学习第十天

条款36&#xff1a;绝不重新定义继承而来的non-virtual函数non-virtual函数执行的是静态绑定&#xff0c;在编译器就已经决定&#xff0c;因此对象对用的函数只和指针的类型有关&#xff0c;而与指针所指的对象无关&#xff1b;记住non-virtual函数的性质&#xff1a;不变性凌驾…

Redis运维和开发学习笔记(7) 内存管理和过期策略

Redis运维和开发学习笔记(7) 内存管理和过期策略 文章目录Redis运维和开发学习笔记(7) 内存管理和过期策略内存回收策略惰性删除定时任务删除maxmemory过期策略allkeys-lru主从搭建测试搭建完毕主从测试结果volatile-lru测试结果volatile-ttl测试结果allkeys-lru内存回收策略 …

Effective C++学习第十一天

条款41&#xff1a;了解隐式接口和编译期多态面向对象编程世界总是以显式接口&#xff08;源码可见的接口&#xff09;和运行期多态&#xff08;virtual&#xff09;解决问题&#xff1b;对于templates及泛型编程的世界&#xff0c;隐式接口和编译期多态显得更加重要&#xff1…

Redis源码分析(零)学习路径笔记

文章目录第一阶段第二阶段 熟悉Redis的内存编码结构第三阶段 熟悉Redis数据类型的实现第四阶段 熟悉Redis数据库的实现第五阶段 熟悉客户端和服务器端的代码实现第六阶段 这一阶段主要是熟悉Redis多机部分的代码实现关于测试方面的文件有一些工具类的文件如下SORT命令的实现一些…

Effective C++学习第十二天

条款47&#xff1a;请使用traits classes表现类型信息STL有五类迭代器分类&#xff0c;input迭代器&#xff08;只读&#xff0c;一次&#xff0c;向前&#xff09;、output迭代器&#xff08;可写&#xff0c;一次&#xff0c;向前&#xff09;、forward迭代器&#xff08;读/…