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++面向对象高级开发课程(第一周)的更多相关文章

  1. C++面向对象高级开发课程(第三周)

    一,类与类之间的关系:继承(Inheritance).复合(Composition).委托(Delegation). 二,复合:表示 is-a ,该设计思想可以参照C语言的 struct . 1. 例 ...

  2. C++面向对象高级开发课程(第二周)

    1. 类中含有指针—— class with pointer member(s) ——的情况经常发生,典型的有:string 类. 2. STL中的 string 类太复杂,copy on write ...

  3. j2ee高级开发技术课程第一周

    一.课程目标 这学期开始了J2EE高级开发技术这门课,在此之前我学习了javaSE,为这门课的学习打下了一定的基础.到这学期的结束我希望我能熟悉javaee,能开发企业级应用,对开发轻量级企业应用的主 ...

  4. 扎西平措 201571030332《面向对象程序设计 Java 》第一周学习总结

    <面向对象程序设计(java)>第一周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ...

  5. 201871010124 王生涛《面向对象程序设计JAVA》第一周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://edu.cnblogs.com/campus/xbsf/ ...

  6. 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结

    面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...

  7. Chromium浏览器高级开发系列第一篇:如何获取最新chromium源码

    背景:     最近摊上一个事儿,领导非要让写一篇技术文章,思来想去,自己接触chrome浏览器时间也不短了,干脆就总结一下吧.于是乎,本文顺理成章.由于有些细节必需描述清楚,所以这次先讲如何拿到ch ...

  8. 《Linux内核分析》课程第一周学习总结

    姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  9. 网易Java高级开发课程随笔

    java学习也有6个月之久,记录下课程相关知识点,目前我还没有掌握,so仅作技术点记录 鉴于在.NET上我封装了一套开发框架,虽去年按.NET封装的思路自己也弄了个java开发框架,还是感觉对java ...

随机推荐

  1. ASP.NET Web配置指南

    利用ASP.NET,可以指定影响服务器上所有的Web应用程序.仅影响单个的应用程序.影响个别页面.或影响Web应用程序中的个别文件夹的配置设置.可以对编译器选项.调试.用户身份验证.错误消息显示.连接 ...

  2. Spark+IDEA单机版环境搭建+IDEA快捷键

    1. IDEA中配置Spark运行环境 请参考博文:http://www.cnblogs.com/jackchen-Net/p/6867838.html 3.1.Project Struct查看项目的 ...

  3. JavaScript简介与使用方法

    1.JavaScript简介 1.1.JavaScript简史 最初:网络通信很慢,网页上的数据要传送到数据库验证,然后再返回错误结果,找客观过程要等很久,于是,网景公司开发出一门新语言,当时Java ...

  4. pyAudio介绍

    概要 pyaudio有这么几个功能: - 提取特征 - 训练并且使用分类器 - 语音分割功能 - 内容关系可视化 python实现,好处有这么几个 - 适合做计算分析类型操作(编码少,效率不低) - ...

  5. yum provides "*/nmcli" and apt-get

    一般来说著名的linux系统基本上分两大类: 1.RedHat系列:Redhat.Centos.Fedora等 2.Debian系列:Debian.Ubuntu等 RedHat 系列 1 常见的安装包 ...

  6. Python开发【Tornado】:搭建文件下载服务、音频文件播放

    Tornado 如何做文件下载 要求:浏览器输入url地址,直接弹窗提示下载 Tornado服务端,搭建文件下载服务 #!/usr/bin/env python # -*- coding:utf-8 ...

  7. JS模块化编程(一)

    需求背景 // 实际开发常需要将一些公用方法打包放在一个js文件,写法大致如下     function f1(){         // ...     }     function f2(){   ...

  8. [解决]WPF 在 win7 系统无法运行:FileNotFoundException

    开发环境:VS2015 + .NET 4.6.2 开发项目1:WPF + CefSharp 开发项目2:WPF 情况:两个项目编译的程序都无法在客户环境的 win7上运行,事件查看器中如下日志: Th ...

  9. 系列解读Dropout

    本文主要介绍Dropout及延伸下来的一些方法,以便更深入的理解. 想要提高CNN的表达或分类能力,最直接的方法就是采用更深的网络和更多的神经元,即deeper and wider.但是,复杂的网络也 ...

  10. Unity 小知识

    1.如何使物体颜色成2D效果 点开材质球的Shader属性,选择Unlit/Color 2.画布属性中的UI Scale Mode中可以设为 S W S S,这样屏幕大小缩放时,画布内的物体大小随之缩 ...