C++面向对象高级开发课程(第一周)
0. 内存分区
计算机中的内存在用于编程时,被人为的进行了分区(Segment),分为:
-“栈区”(Stack)
-“堆区”(Heap)
-全局区(静态 区,Static)
-文字常量区和程序代码区
在前面的课程中,我们主要直接涉及到的是栈区的内存,在你的程序中,函数的参数值,局部变量的值等都被存在 了“栈区”,这部分的内存,是由系统来帮助你来管理的,没有特殊情况的时候,你是不需要对其进行特别处理的。计算机中内存的分配如下图。
而针对堆区的内存,一般由程序员进行分配和释放, 使用堆内存的原因一般是
-“栈上内存比较小,不够用”
-“系统管理内存的方式死板,不方便用”
对于堆上的内存,被程序员手动分配后,若程序员 不释放就可能会出现“内存泄漏”。很多企业级的应用,都因为内存泄漏而在“正常”运转很长时间后,轰然“坍塌”。在后面的入门课程中,我们会简单的对这块 的知识进行介绍。
全局区、文字常量区和程序代码区在我们入门阶段,暂时还可以不去过多理解(甚至看不懂也无妨),只需要知道他们的大致作用即可——全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放;文字常量区是用于储存常量字符串的, 程序结束后由系统释放;程序代码区用于存放函数体的二进制代码。
1. C++类的写法
C++类的两大经典写法:
Class without pointer member(s) 比如 课程中定义的 Complex 类。
and
Class with pointer member(s) 比如 系统中的 string 类。
2. C++正规、大气的写法
2.1 使用“防卫式声明”
#ifndef _COMPLEX_
#define _COMPLEX_ class Complex
{
//some declaration
} #endif
2.2 使用“构造函数初始值列表”
尽量在声明构造函数时使用“构造函数初始值列表”,因为这样在变量的声明阶段就赋予了值,有助于提高效率。
2.3 使用“const”
为了代码在以后被其他程序员复用中,在“顶层”能使用const关键字限定行为,所以我们在做“底层”工作时,要充分考虑到使用const限定函数行为。
同时注意C++语法的“顶层const”原则。
另外,在类body的定义中,也尽量使用“const”语法。
2.4 使用”引用“
尽量考虑使用“引用”这一语法。因为在传递的过程中开销比较小—— 一个4字节的指针。
但是引用也有一些缺点,比如引用的不安全性——引用的母体的值可能会通过子体被修改。所以我们可以在引用的地方考虑使用const。
3. inline
函数若在 class body 内完成定义,该函数便自动成为 inline “候选人”。
太复杂的函数无法成为“真正的” inline function,即便是用 inline 声明。
4. 参数传递
两种方式:
pass by value 程序栈内数据直接拷贝,开销比较大。
and
pass by reference (to const) “引用”语法的底层实现是指针,所以传4字节的指针开销比较小。形式美观。
inline complex& complex::operator += (const complex& r)
{
return __doapl (this, r);
}
6. 友元
6.1 提高性能
在一些情况下,为了提高性能,请尽量通过友元实现数据存取。
因为通过使用友元语法,可以省略掉一步多余的——通过类共有方法实现存取类私有数据——操作,因此可以提高性能。但也破坏了封装。
6.2 特性
同一类的各个对象互为友元。例如下面代码:
class complex
{
public:
Complex (double r = , double i = )
: re(r), im(i)
{ } int func(const complex& param)
{ return param.re + param.im; } private:
double re, im;
}; int main()
{
complex c1(, );
complex c2(); c2.func(c1);
}
7. “引用”的不适用场景
inline complex&
__doapl (complex* ths, const complex& r)
{
ths->re += r.re; //第一参数将会被改动
ths->im += r.im; //第二参数将不会被改动
return *ths;
}
因为 r 是一个引用,当函数执行完成,空间被回收以后,引用这一实体将不存在。
8. 如何实现C++高性能
侯杰认为,好的C++程序应该具备
- 数据尽可能放在 private 区
- 参数尽可能使用 reference 传递
- 返回值尽可能使用 reference 传递
- class body 中尽可能使用 const 语法
- 尽可能使用 构造函数初始值列表
9. 运算符重载
9.1 成员函数
作为类的成员函数,运算符重载要写成如下的形式。“+=”运算符右边的操作数作为函数的参数被传递;“+=”运算符左边的操作数作为类内部的 this 指针。
inline complex& complex::operator += (const complex& r)
{
return __doapl (this, r);
}
为了便于理解,可以写成如下形式(语法错误,但是便于理解)。
// 语法有错误,但是便于理解。注意第一个参数:this
inline complex& complex::operator += (this, const complex& r)
{
return __doapl (this, r);
}
9.2 非成员函数
作为非成员函数的重载,函数定义时operator关键字前面不应该有 “类名::”限定符。代码如下:
inline complex operator + (const complex& x, const complex& y)
{
return complex (real (x) + real (y), imag (x) + imag (y));
}
其中,return complex(......)表示声明了一个临时对象,并将其直接返回。这样的写法——返回临时对象——在STL中很常见。
如果作为“成员函数”的重载,代码如下:
inline complex& complex::operator += (const complex& r)
{
return __doapl (this, r);
}
10. return by reference 语法分析
传递者无需知道接收者是从reference形式接收。
11. STL :: complex类中的优良写法
- initialization list (构造函数初始化列表)
- 函数 const
- 参数传递尽量 pass by reference
- 函数返回值尽量 return by reference
- 数据声明在 private
12. 关于引用的讨论
引用传递的底层实现是一根4字节的指针,所以开销相比较而言较小。
但是对于“基本内置类型”比如 bool, double, char[4]以内, int直接传递其本身与传递引用效率是一样的,这就需要程序员根据编程规范自己取舍。
13. 成员函数声明时const
在声明成员函数时加上const关键字,如代码所示:
class complex
{
public:
double real () const { return re; }
};
表示该函数不被允许修改类中的成员变量。
14. C++组成部分
C++由两部分组成:C++语言本身 和 C++标准库。
15. STL complex类代码区域划分
主要分成三部分:前置声明、类声明、类定义。
#ifndef __COMPLEX__
#define __COMPLEX__ /* 0 前置声明 */
#include <cmath> class ostream;
class complex; complex& __doapl ( complex* ths, const complex& );
/* end 0 前置声明 */ /* 1 类声明 */
class complex
{ };
/* end 1 类声明 */ /* 2 类定义 */
complex::function....
/* end 2 类定义 */ #endif // __COMPLEX__
16. 附录
complex 类代码如下:
#ifndef __MYCOMPLEX__
#define __MYCOMPLEX__ class complex;
complex&
__doapl (complex* ths, const complex& r);
complex&
__doami (complex* ths, const complex& r);
complex&
__doaml (complex* ths, const complex& r); class complex
{
public:
complex (double r = , double i = ): re (r), im (i) { }
complex& operator += (const complex&);
complex& operator -= (const complex&);
complex& operator *= (const complex&);
complex& operator /= (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:
double re, im; friend complex& __doapl (complex *, const complex&);
friend complex& __doami (complex *, const complex&);
friend complex& __doaml (complex *, const complex&);
}; inline complex&
__doapl (complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
} inline complex&
complex::operator += (const complex& r)
{
return __doapl (this, r);
} inline complex&
__doami (complex* ths, const complex& r)
{
ths->re -= r.re;
ths->im -= r.im;
return *ths;
} inline complex&
complex::operator -= (const complex& r)
{
return __doami (this, r);
} inline complex&
__doaml (complex* ths, const complex& r)
{
double f = ths->re * r.re - ths->im * r.im;
ths->im = ths->re * r.im + ths->im * r.re;
ths->re = f;
return *ths;
} inline complex&
complex::operator *= (const complex& r)
{
return __doaml (this, r);
} inline double
imag (const complex& x)
{
return x.imag ();
} inline double
real (const complex& x)
{
return x.real ();
} inline complex
operator + (const complex& x, const complex& y)
{
return complex (real (x) + real (y), imag (x) + imag (y));
} inline complex
operator + (const complex& x, double y)
{
return complex (real (x) + y, imag (x));
} inline complex
operator + (double x, const complex& y)
{
return complex (x + real (y), imag (y));
} inline complex
operator - (const complex& x, const complex& y)
{
return complex (real (x) - real (y), imag (x) - imag (y));
} inline complex
operator - (const complex& x, double y)
{
return complex (real (x) - y, imag (x));
} inline complex
operator - (double x, const complex& y)
{
return complex (x - real (y), - imag (y));
} inline complex
operator * (const complex& x, const complex& y)
{
return complex (real (x) * real (y) - imag (x) * imag (y),
real (x) * imag (y) + imag (x) * real (y));
} inline complex
operator * (const complex& x, double y)
{
return complex (real (x) * y, imag (x) * y);
} inline complex
operator * (double x, const complex& y)
{
return complex (x * real (y), x * imag (y));
} complex
operator / (const complex& x, double y)
{
return complex (real (x) / y, imag (x) / y);
} inline complex
operator + (const complex& x)
{
return x;
} inline complex
operator - (const complex& x)
{
return complex (-real (x), -imag (x));
} inline bool
operator == (const complex& x, const complex& y)
{
return real (x) == real (y) && imag (x) == imag (y);
} inline bool
operator == (const complex& x, double y)
{
return real (x) == y && imag (x) == ;
} inline bool
operator == (double x, const complex& y)
{
return x == real (y) && imag (y) == ;
} inline bool
operator != (const complex& x, const complex& y)
{
return real (x) != real (y) || imag (x) != imag (y);
} inline bool
operator != (const complex& x, double y)
{
return real (x) != y || imag (x) != ;
} inline bool
operator != (double x, const complex& y)
{
return x != real (y) || imag (y) != ;
} #include <cmath> inline complex
polar (double r, double t)
{
return complex (r * cos (t), r * sin (t));
} inline complex
conj (const complex& x)
{
return complex (real (x), -imag (x));
} inline double
norm (const complex& x)
{
return real (x) * real (x) + imag (x) * imag (x);
} #endif //__MYCOMPLEX__
C++面向对象高级开发课程(第一周)的更多相关文章
- C++面向对象高级开发课程(第三周)
一,类与类之间的关系:继承(Inheritance).复合(Composition).委托(Delegation). 二,复合:表示 is-a ,该设计思想可以参照C语言的 struct . 1. 例 ...
- C++面向对象高级开发课程(第二周)
1. 类中含有指针—— class with pointer member(s) ——的情况经常发生,典型的有:string 类. 2. STL中的 string 类太复杂,copy on write ...
- j2ee高级开发技术课程第一周
一.课程目标 这学期开始了J2EE高级开发技术这门课,在此之前我学习了javaSE,为这门课的学习打下了一定的基础.到这学期的结束我希望我能熟悉javaee,能开发企业级应用,对开发轻量级企业应用的主 ...
- 扎西平措 201571030332《面向对象程序设计 Java 》第一周学习总结
<面向对象程序设计(java)>第一周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ...
- 201871010124 王生涛《面向对象程序设计JAVA》第一周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://edu.cnblogs.com/campus/xbsf/ ...
- 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结
面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...
- Chromium浏览器高级开发系列第一篇:如何获取最新chromium源码
背景: 最近摊上一个事儿,领导非要让写一篇技术文章,思来想去,自己接触chrome浏览器时间也不短了,干脆就总结一下吧.于是乎,本文顺理成章.由于有些细节必需描述清楚,所以这次先讲如何拿到ch ...
- 《Linux内核分析》课程第一周学习总结
姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- 网易Java高级开发课程随笔
java学习也有6个月之久,记录下课程相关知识点,目前我还没有掌握,so仅作技术点记录 鉴于在.NET上我封装了一套开发框架,虽去年按.NET封装的思路自己也弄了个java开发框架,还是感觉对java ...
随机推荐
- poj1850Code
Code Transmitting and memorizing information is a task that requires different coding systems for th ...
- java 类中的细节
java 中类: 类是用于描述统一类型的对象的一个抽象的概念,类中定义了这一类对象所因具有的静态和动态属性. 举例: 瓶子静态: 有一个口.长长的形状-->java类中的成员变量动态属性: 可以 ...
- First normal formal Second normal form
https://en.wikipedia.org/wiki/First_normal_form https://en.wikipedia.org/wiki/Second_normal_form A r ...
- yum provides "*/nmcli" and apt-get
一般来说著名的linux系统基本上分两大类: 1.RedHat系列:Redhat.Centos.Fedora等 2.Debian系列:Debian.Ubuntu等 RedHat 系列 1 常见的安装包 ...
- vue - vue-cli脚手架安装和webpack-simple模板项目生成
ue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一.安 ...
- LoadRunner-参数化(参数间关联)
多用户测试,每个用户账号对应一个密码,账号和密码需要一 一关联才能登录成功. 1.在已经对账号进行参数化后,选中密码的值->右键选择Replace with a Parameter,参数名为pa ...
- 几个经典的css技巧
使用 line-height 垂直居中 line-height:24px; 使用固定宽度的容器并且需要一行垂直居中时,使用 line-height 即可(高度与父层容器一致),更多的垂直居中总结可以看 ...
- 控制div显示隐藏(有文字图片介绍)
<div class="toggle"> <p id="zi">收起</p> <p id="zhe" ...
- dedecms自增标签[field:global.autoindex/]的运用
用bootstrap建站时用到幻灯片切换模块,里面有个active(下面代码中的data-slide-to="0"),其余的按顺序递增(1,2),如果用dedecms就可以用aut ...
- Android开发之改动屏幕方向
有的场景下.我们须要把手机屏幕方向改变,以下是我写的一个样例. xml页面文件: <RelativeLayout xmlns:android="http://schemas.andro ...