C++高级编程课程讲义----
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
// 通过p[ i ]来操作每个数组
// 不能使用 delete p或者delete[] p
字符集和字符串 (1) 字符编码
ANSI、UNICODE和UTF-8
MultiByte和WideChar
wchar_t, “L”前缀, wcslen, wcscpy, wcslen
wchar_t p1[] = L“abcd”; 考察:wcslen(p1)和sizeof(p1)的结果
使用数组
// 注意结尾的‟\0‟ // 自动添加‟\0‟结尾
char p1[10] = {„a‟,„b‟,„c‟,„d‟,„\0‟}; char p2[] = {“abcd”}; char p3[] = {“abcd”};
char p4[] = {'a','b','c','d'};
考察 (2) p2 == p3 ?
数组 (5) 动态创建复杂数组
二维数组
int n = 3;
int m = 2; delete[] p;
int (*p)[3] = new int[2][3];
交错数组
// p数组包含两个元素,每个元素都是int*类型
int* p[m];
p[1] = new int[3];
delete p[1];
double* p = &a;
double a = 10; (2)&p含义是什么?
考察: (1)p是指针变量,则sizeof(p)=?
引用的定义
int& b = a; (2) a=? b = 1000;
int a = 100; 考察: (1)&a与&b的关系?
引用必须在声明时立即初始化,不允许空引用
引用一旦初始化,就不能再引用其它数据
引用和被引用的变量实际上代表同一个内存的 数据
指针与引用 (2) 混合使用
指针指向某个引用
double& b = a; double *p = &b;
double a = 100;
考察: (1) &a, p和&b的关系 (2)修改a, b或*p的值,另两个是否联动
C++高级编程
Overview
Module 1 : 面向过程的C++ Module 2 : 面向对象的C++
Module 3 : C+Байду номын сангаас设计模式
Module 1 : 面向过程的C++
从C到C++ 内存管理
数组
字符集和字符串 指针和引用 函数 其它
从C到C++
防止”野指针”:回收内存后指针会自动为NULL吗?
Demo: 动态扩充的字符串缓冲区
数组 (1) 声明及初始化
int a[]={1,2,3};
int b[3]={1,2,3};
int c[5]={1,2,3}; // c[3]和c[4]的值默认为0
int a1[2][3]={{1,2,3},{4,5,6}}; int a2[2][3]={{1},{}}; int a3[][3]={{},{1,2,3}}; // 初始化,第一行为1,0,0;第二行为0,0,0
数组 (3) 指针表现形式
一维数组指针表示
const int ARRAY_SIZE = 5;
int a[ARRAY_SIZE] = {1,2,3,4,5}; int *p = a; 考察: (1) a+i, p+i, *(a+i), *a+i, p[i] 的含义
(2) p++偏移几个字节?a++呢?
// 仅仅声明一个字符数组而非字符串
(1) sizeof(p), strlen(p)的值分别是多少?
字符集和字符串 (4) 字符串操作函数
修改单个字符
char p1[10] = “abcd”;
char* p2 = “abcd”;
p1[0] = „x‟ p2[0] = „x‟
// p2指向常量字符串
mbstowcs_s和wcstombs_s MultiByteToWideChar, WideCharToMultiByte
字符集和字符串 (2) 兼容字符集
Windows平台与字符集
Visual C++编译器字符集设置选项
_UNICODE _MBCS TCHAR, _tcslen, “_T”
兼容字符集
TCHAR t[] = _T("aaa"); // 如果编译器定义了_UNICODE,sizeof(t)=8, // 如果定义了_MBCS,sizeof(t)=4
字符集和字符串 (3) 声明字符串
使用指针
char *p1 = "abcd";
char *p2 = "abcd";
考察:内存中有几个”abcd”存在, p1 == p2是否成立?
// n不必是常量 // 错误 // 错误
double *p = new double[10]; int n = 10; double *p = new double[n]; double *p = new double[400][300]; double **p = new double[400][300];
// OK // 错误,常量字符串不可修改
字符串长度
char p1[] = "a\t\nc";
考察: strlen(p1)和sizeof(p1)
模拟编写strcpy方法
为何采用const作为参数
为何返回char* „\0‟会被拷贝吗? Demo
指针与引用 (1) 概念
指针与指针变量
const int a = 100; const int& b = a; int& b = a; // OK // 错误
指针与引用 (5) Practice
char s1[] = "abcdefg"; char s2[] = "1234567"; char* p1 = s1; const char* p2 = s1; char* const p3 = s1; const char* const p4 = s1; 考察:下列哪些语句有效: p1[0]=‟k‟; p2[0]=‟k‟; p3[0]=‟k‟; p1=s2; p2=s2; p3=s2; p4=s2;
int a4[2][]={{1,2,3},{4,5,6}};
int a5[][3]={1,2,3,4,5,6};
// 错误。必须声明第二维的数目
// 正确
数组 (2) 数组的内存形式
数组在内存中的存放
全局数组在静态存储区域中存放
局部数组,一般在堆栈上存放
在堆上动态分配内存
线程堆栈的限制:double arr[500][300] ?
函数 (1) Extern
C语言中的Extern和Static C++中的extern “C”
允许在C++中调用C编写的函数 允许在C中调用C++编写的函数
cfile.h文件: extern int add(int x, int y)
cfile.c文件: int add(int x, int y) {return x + y;} cpp.cpp: extern “C” { #include “cfile.h”} …… 其它格式: extern “C” int add(int x, int y); extern “C” { int add(int x, int y); int sub(int a); }
// 将二维数组展开成一维数组的方式访问 // 错误! p+i, *(p+i), *p+i的含义
使用指向一维数组的指针来访问二维数组
int (*p)[3]=a; int *p[3]=a; // 也可写成:int (*p)[3](a); // 错误! Int* p[3];
考察:p, p+i, *(p+i), *p+i, *(p+i)+j, *(*(p+i)+j)的含义
语法增强
新的运算符
变量声明更加灵活 函数重载
引用
类型安全性
面向对象
封装
继承 多态
内存管理
在stack上分配内存
简单数据类型
不使用new创建对象实例 函数调用完成自动销毁
线程堆栈的限制
malloc 还是 new ?
在Heap上分配内存
检测内存泄漏
指针常量
int a =100; int b = 200; int* const pci = &a; // pci不能再指向别的地址 *pci = 1000; // 可以通过修改*pci来修改a的数据 pci = &b; // 错误 考察:如果有 const int* const pci = &a, 则情况如何?
函数调用
(*fun)(10,20);
函数指针作为参数传递
void process(int x, int y, int (*f)(int,int)) { … …} process(10,20,max);
函数 (3) 函数指针
设有函数定义: int myequal1(char* s1,char* s2){...} 类型定义: 则可以声明: 并且调用:
字符集的转换 char p2[10]; // len = 4 ‟\0‟字符不计入拷贝字符数目
wchar_t p1[] = L"abcd"; int len = wcstombs(p2, p1, sizeof(p1)); wchar_t *p3 = (wchar_t*)malloc( 100); mbstowcs(p3, p2, 100);
typedef int (*equal)(char*,char*); equal eq=myequal1; (*eq)(s1,s2);
函数 (4) 缺省参数
void f(int i, int j=10, int k=20) { … … } 调用: f(1,20),相当于:f (1,20,20) 而: f(1), 相当于:f(1,10,20)
Demo: 如何在C++和C之间实现互操作
函数 (2) 函数指针
声明原型
int (*fun)(int x,int y); 或者 int (*fun)(int,int);
指针赋值
设存在函数 int max(int i, int j) {… …}
int (*fun)(int,int)(max); 或者fun=max;
引用一个地址
double& b = a; double *p = &b; // p和rp是完全相同的,且都是变量a的地址 sizeof(rp) = ?
double a = 100; double* &rp = p; 考察:sizeof(b)=?
指针与引用 (3) 作为参数传递
按值传递 按地址传递 按引用传递
注意
缺省参数必须出现在所有非缺省参数的后面 防止函数重载时的二义性
函数 (5) 参数个数不定
回顾 printf(“%s”, ……) 编写自定义得可变参数个数函数 (stdarg.h)
data++; }
void Increase(int& data) { void main() {
int mydata = 10;
Increase(mydata); }
指针与引用 (4) 指针与常量
指向常量的指针
int a =100; int b = 200; const int* pci = &a; // pci不能直接修改a地址中的数据 a = 1000; // 可以通过修改a的数据从而间接修改*pci *pci = 1000; // 错误 pci = &b; // OK. Pci可以指向另一个地址,不再与a相关 考察: 如果a被定义为:const int a = 100,那么: int* pci = &a; 是否成立?
指针与引用 (4) 引用与常量
将一个引用设置为常量后,不能通过该引用修改 数据;但仍可通过被引用的变量来改变:
int a = 100; const int& b = a; // b与a是同一内存,但不能直接修改b
b = 1000;
a = 1000;
// 错误
// OK
被引用的数据是常量,引用本身也必须是常量:
二维数组指针表示
行地址和列地址
int a[ ][3] = {{1,2,3},{4,5,6}}; 考察:a, a+i, *(a+i), *(a+i)+j, *(*(a+i)+j), &a[ i ][ j ]的含义
数组 (4) 二维数组的指针表示
使用一级指针访问二维数组
int a[ ][3] = {{1,2,3},{4,5,6}}; int *p=a[0]; int *p = a; 考察: