12.优先使用前置操作符

#include <iostream>
using namespace std;
class A
{
private:
int num;
public:
A operator++(); //前置++
A operator++(int); //后置++
};
A A::operator++()
{
(*this).num=(*this).num+1; //无须构造一个临时对象
return (*this);
}
A A::operator++(int)
{
A p1; //得先构造一个临时对象;
p1.num=(*this).num;
(*this).num=(*this).num+1;
return p1;
}

因为后置++的实现需要构造一个临时对象,当A类型对象(即被操作对象)很大时,其将会花费较长时间去构造对象,所以能用前置++解决的问题不用后置++解决。

**13.掌握变量定义的位置与时机 **

变量的使用规则是 :“当你需要时在定义”,在能满足需要的情况下(因为有时候不得不定义一些作用域较大的变量),尽可能的降低变量作用域的大小。

如果把所有的变量都在程序开头进行定义的话,当别人阅读你的代码时,需要不停地往前去看你这个变量是什么含义(就算是自己很长时间后再来阅读也会这样麻烦),所以在需要使用这个变量时在定义可以较快的使他人阅读自己的代码,增加了代码的可读性。

**14.小心typedef使用中的陷阱 **

不要认为typedef与宏定义等同,二者是有区别的。

#include <iostream>
#define p1 int*
using namespace std;
typedef int* p2
int main()
{
p1 a,b;
p2 x,y;
int c;
a=&c;
b=&c;
x=&c;
y=&c;
cout<<a<<endl<<b<<endl<<x<<endl<<y;
return 0;
}

结果会报错,显示“b=&c”有错,int*类型的值不能赋值给int类型的实体。

也就是b在定义时并没有定义为int *类型的而是定义成立int类型的,这是因为宏定义只是简单地符号替换,而typedef则不同,其可以有int *定义变量时一样的效果。

15. 尽量不要使用可变参数

int nasa(int a,…)其为含有可变参数函数的定义形式。

c语言中的printf(),和scanf()都是含有可变参数的函数,其在使用时可以支持任意数量,任意类型的参数。

虽然这样看似十分方便灵活但是其有很大的缺点。

(1)其十分不安全,其不会进行类型安全检查。

printf("%d,%c".256,256)

因为其printf的第二个参数应该接收字符类型,而其传的是int类型

其会对int类型的数据进行强制类型转换为字符类型,因为字符类型的长度小于int类型的,所以其发生内存截断(如果截断后的数据正好在字符类型数据范围内则不会报错,程序会发生意想不到的错误)。

(2)可变参数不支持自定义数据类型

例如printf函数只能支持基本数据类型,这也是为什么c++用输入输出流对象来进行基本的输入输出的原因之一,cout与cin就支持自定义数据类型(通过运算符重载),而且其使用方便,很随意不需要再像使用printf那样进行格式化输出,而且还极易出错。

c++有自己的方法实现类似于可变参数的这种功能,虽然没有其灵活但是其很安全。(其实就是通过函数重载来实现的)

class A
{
private:
public:
void nasa(int);
void nasa(char);
void nasa(int,char);
void nasa(char,int);
......
};

尽量不要使用可变参数,因为其真的很不安全,而且极易出错

16.不要用goto语句(不要用就对了)

17. 小心隐式转换带来的麻烦

显示强制类型转换虽有时候也会带来一定的麻烦但其是人为可控的,容易找到。但是隐式类型转换是编译器自动进行的,是很难察觉到的。

(1)基本类型的隐式转换

基本类型一般在运算时都是向更宽的类型转换。

(2)T到void的隐式转换

c语言支持void与其他类型的指针之间进行双向转换,而c++只支持其他类型的指针转换为void

(即任何类型的指针都可以赋值给void*类型,从而变为不指向任何类型的指针)

(3)子类到父类的隐式转换

即子类对象可以对父类对象进行赋值

(但父类不能隐式转换为子类,即父类对象不能对子类对象进行赋值)

(4)重载类型转换符与转换构造函数中涉及的隐式转换

重载类型转换符引起的隐式转换

class A
{
public:
int x;
int y;
public:
A(int a,int b):x(a),y(b){}
operator double()
{
return double(x)/double(y)
}
};
int main()
{
A P1(1,2);
cout<<p1;
return 0;
}

结果输出0.5,没有重载<<运算符为什么可以输出自定义类型呢?

其实因为当编译器没有找到合适的operator<<函数时,其会看能不能把带输出对象转换成能够执行operator<<函数的类型,正好重载的double类型转换符可以把其转换成double类型,所以待操作对象其被自己重载的double函数给隐式转换成double类型

1.0/2.0等于0.5后再调用operator<<函数进行输出

所以当重载了类型转换符的类对象如果没有对输出流对象进行重载的话,不能进行输出(否则会产生意料不到的麻烦)。

转换构造函数引起的隐式转换

(也包括含有一个参数的构造函数)

class A
{
public:
A(int a):num1(a){}
A(int a1,char a2='@'):num1(a2),num2(a1){}
void output();
private:
int num1;
char num2;
};
int main()
{
int w=2;
char ww='a';
A p1(w);
p1.output();
p1=ww;
p1.output();
return 0;
}
void A::output()
{
cout<<num1<<" "<<num2<<endl;
}

结果为:

2

0 a

原因是当p1=ww(一个char类型的对象值理论上是不能赋给一个类类型的对象的,其之所以可以赋值是因为编译器利用此类所含的构造函数A(int a1,char a2=’@’ ):num1(a1),num2(a2)对其进行了隐式转换成此类类型。)

为了解决这个问题应该在含有单参数的构造函数前加上explicit关键字

explicit  A(int a):num1(a){}
explicit A(int a1,char a2='@'):num1(a2),num2(a1){}

这时候p1=ww语句就是被认为是不合法的,无法通过编译。

总结(4):由重载类型转换符带来的隐式转换问题,要注意是否重载了operator<<函数,否则不要试图输出本类对象。

由转换构造函数(包含单参数的构造函数)带来的隐式转换问题,注意在其构造函数定义前加上explicit关键字

18. 正确区分void与void *

(1)void是无类型的意思

①函数无返回值时应该将其声明为void类型

void nasa(参数表列)

②函数无参数时应该声明void

返回值类型 nasa(void)

实际可以写可以不写,但是有的编译器在没有void的情况下会报错,为了代码的可移植性,在编程中尽量加上void。

(2)void *(意思是指针不确定其指向什么类型)

不同类型的指针是不能直接相互转换的

int *p1;
char *p2
p1=p2

这是不允许的,其必须通过强制类型转换

p1=(int *)p2 这是合法的

而void *不一样,任何类型的指针都可以转换成void *

void *p1;
int *p2;
p1=p2;

这是允许的,c语言中还允许void *类型直接转换成其他指针类型,但是在c++中就不允许这么干。但是可以强制类型转换

p2=(int *)p1

一般类型的指针支持加上或减去一个数,

int *p;
int a=*(p+2)

p指针加上2表示p指针所指空间再向下偏移两个字节

但是void *类型的不行,因为其无法确定其指向的是什么类型,即无法确定其所指向空间的大小,因此不能进行加减一个数。

改善c++程序的150个建议(读后总结)-------12-18的更多相关文章

  1. 编写高质量代码_改善C++程序的150个建议 读书笔记

    这几天看了下这本书<编写高质量代码_改善C++程序的150个建议>,觉的蛮有收获的,再次记录下自己以前不清晰的知识点,以供学习. 编写符合标准的main函数 C语言标准规定了main函数的 ...

  2. 改善c++程序的150个建议(读后总结)-------19-26

    19. 明白在c++中如何使用c c++可以兼容c的绝大部分代码,但是还是有一部分不能兼容. c语言的编译器在调用函数时会把函数翻译成 : "_函数名",例如: int nasa( ...

  3. 改善c++程序的150个建议(读后总结)-------10-11

    10. 优化结构体中元素的布局 结构体变量所占空间大小并不是其所含类型所占字节数之和,其所占内存字节数涉及到字节对齐. 字节对齐 :变量在内存中储存都是以字节数为单位,每一个字节都有自己的地址,逻辑上 ...

  4. 改善c++程序的150个建议(读后总结)-------0-9

    0. 不要让main 函数返回 void 入口函数main()返回类型应该为 int, 即程序结束时return 0 表示程序正常返回,函数结束时 return -1 值表示程序异常返回, 如果不显式 ...

  5. 改善c++程序的150个建议(读后总结)-------27-35

    27. 区分内存分配的方式 c++中内存分为5个不同的区 ①栈区 栈是一种特殊的数据结构,其存取数据特点为(先进后出,后进先出).栈区中主要用于存储一些函数的入口地址,函数调用时的实参值以及局部变量. ...

  6. 改善C++ 程序的150个建议学习之建议7:时刻提防内存溢出

    作为一个程序员,对内存溢出问题肯定不陌生,它已经是软件开发历史上存在了近40年的大难题.在内存空间中,当要表示的数据超出了计算机为该数据分配的空 间范围时,就产生了溢出,而溢出的多余数据则可以作为指令 ...

  7. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

  8. 改善java程序的151个建议

    <编写高质量代码-改善java程序的151个建议> --秦小波 第一章.开发中通用的方法和准则 1.不要在常量和变量中出现易混淆的字母 long a=0l; --> long a=0 ...

  9. 编写高质量代码改善java程序的151个建议——导航开篇

    2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...

随机推荐

  1. 攻防世界 reverse BabyXor

    BabyXor     2019_UNCTF 查壳 脱壳 dump 脱壳后 IDA静态分析 int main_0() { void *v0; // eax int v1; // ST5C_4 char ...

  2. 图解双链表(Java实现)

    原创公众号:bigsai 文章已收录在 全网都在关注的数据结构与算法学习仓库 前言 前面有很详细的讲过线性表(顺序表和链表),当时讲的链表以但链表为主,但实际上在实际应用中双链表的应用多一些就比如Li ...

  3. 走进docker-聊聊docker网络

    容器网络概念 首先了解下linux的网络构成概念 命名空间: Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信:Docker利用这一特性,实现不容器间的网 ...

  4. MyBatis工程搭建&MyBatis实现Mapper配置查询

    一.MyMyBatis工程搭建 新建Maven项目:mybatis-demo 准备数据源 1 # 删除mybatis_demo数据库 2 drop database if exists mybatis ...

  5. WebGPU[1] 三角形

    代码见: https://github.com/onsummer/my-dev-notes/tree/master/webgpu-Notes/01-triangle 如果本篇的代码不能跑了,请联系我或 ...

  6. Node.js核心入门

    前言: 因为以前学习Node.js并没有真正意义上的去学习它,而是粗略的学习了npm的常用命令和Node.js一些模块化的语法,因此昨天花了一天的时间看了<Node.js开发指南>一书.通 ...

  7. 99%的Python用户都不知道的f-string隐秘技巧

    f-string想必很多Python用户都基础性的使用过,作为Python3.6版本开始引入的特性,通过它我们可以更加方便地向字符串中嵌入自定义内容,但f-string真正蕴含的功能远比大多数用户知道 ...

  8. [Fundamental of Power Electronics]-PART I-6.变换器电路-6.2 变换器简单罗列

    6.2 变换器简单罗列 变换器的数量可能有无穷种,因此将其全部列出是不可能的.这里给出了一个简单的罗列清单. 首先考虑含单个电感的单输入单输出变换器的类别.可以在电源和负载之间进行连接电感的方法数量是 ...

  9. AutoAssign源码分析

    目录 AutoAssign源码分析 一. 简介 二. 论文理论 2.1 联合表示 2.2 正样本权重 2.3 负样本权重 2.4 总的loss 2.5 补充loss 三. 论文代码 四. 总结 五. ...

  10. 软工AI Bot NABCD分析

    目标: 打造一个基于大数据的 IT 问答机器人服务,通过运用人工和AI 技术,极大提高问答产品的用户满意度. 适合高校<软件工程>,<人工智能>课程作为结对编程或者团队项目. ...