西工大《C++程序设计》——(三)

文章目录

    • 第13讲:数组的定义和使用
    • 第14讲: 数组与函数
    • 第15讲:字符串的处理
    • 第16讲:数组的应用
    • 第17讲:指针的定义与使用
    • 第18讲:指针与数组
    • 第19讲:指针与函数

第13讲:数组的定义和使用

  1. 一维数组的定义、内存形式(连续存储)、初始化。
  2. 静态数组与动态数组的初始值。
  3. 二维数组的定义、内存形式(按行连续存储)、初始化。
  4. 多维数组的引用。

第14讲: 数组与函数

  1. 数组元素作为函数参数。
  2. 整个数组作为函数参数,传递的是数组的首地址,所以实参和形参为同一个对象。
  3. 数组作为函数参数时,编译器不检查数组的长度,因此将数组的首地址传入函数时,常需传入另一个参数来表示实参数组的长度。但是多维数组除第一维外其余维数的长度不可省略,否则无法确定数组的基类型。

第15讲:字符串的处理

  1. 编译器在编译字符串常量时自动在其末尾加上结束符'\0'
  2. 【字符串处理函数】
  3. 【字符串对象】:其类在string头文件里定义,字符串对象不需结束符\0,且采用动态内存管理,还会检查内存越界。
  4. 字符串对象可用字符串常量直接进行赋值而不需调用字符串处理函数。
  5. 字符串对象的操作:赋值运算、连接运算、关系运算。

第16讲:数组的应用

  1. 用数组解决排序问题:交换排序、选择排序。
  2. 用数组解决查找问题:顺序查找、二分查找。
  3. 【二分查找实例】:
#include 
using namespace std;
int BinarySearch(int A[], int n, int find){
	int low, upper, mid, result=-1;
	low = 0, upper = n-1;
	while(low<=upper){
		mid = low +(upper-low)/2;	// 可防止low+upper溢出
		if(A[mid]<find)
			low = mid+1;
		else if(A[mid]>find)
			upper = mid-1;
		else
			result = A[mid];	// result为单一出口
	}
	return result;
}

第17讲:指针的定义与使用

  1. 数据的写入与读出均与内存打交道,而指针类型就是处理内存地址的数据类型。指针不仅能提高程序的效率,而且能使一个函数访问另一个函数的局部变量,因此指针是函数进行数据交换必不可少的工具。
  2. 程序中的数据对象在生命周期内总是占用一定的存储空间,有确定的存储位置。按对象名称存取对象为直接访问,通过指针存取对象为间接访问。
  3. 由于指针的特殊性,指针的初始化和赋值是受一定约束的,只能是以下四种值:
  • 0常量表达式
int a, z=0;
int *p1=a;	// 错误,地址初值不能为变量
p1 = z;		// 整型变量不能作为指针值,即使其值为0
p1 = 4000; 	// 错误,整型数据不能作为指针值
p1 = null; 	// 正确
p1 = 0; 	// 正确

  • 类型相同的对象的地址值
int a, *p1;
float b, *p2;
p1 = &a; 	// 正确
p1 = &bl;	// 错误
p2 = &b;	// 正确
  • 基类型相同的指针变量的值
  • 对象存储空间的下一个有效地址
  1. 【指针的有效性】:指针指向有确定存储空间的对象时为有效指针,否则为无效指针。
  2. 【无效指针】:0值指针(空指针);未初始化、未赋值或运算后指向未知对象的指针;指向对象被释放后值却未变的指针。
  3. 【指针运算】:指针作用在连续存储空间上才有意义,比如指针加减整数、同类型指针相减、指针间的关系运算。
  4. 【指针的限定】:
const int a=10, b=20;
const int *p;
p = &a;
p = &b;
*p = 12;	// 错误,*p是只读的
  • const对象的地址赋给非const基类型的指针变量是错误的。
const double pi=3.14;
double *p=&pi;	// 错误,p非const指针
const double *ptr=&pi;	// 正确,ptr为const型指针
  • 允许把非const对象的地址赋给const基类型的指针变量,但不可通过const基类型的指针改变其所指的非const对象的值。const基类型的指针常用于函数形参以保护限定实参为只读,此举可增加程序健壮性。
const double pi=3.14;
const double *p=&pi;	// 正确
double f=3.14;	// f为非const对象
p = &f;	// 正确
f = 3.14159;	// 正确
*p = 3.141;	// 错误,无法通过const指针解引用来修改所指对象的值
  • const指针:指针本身不可改变值,但其所指变量可改变值。
int a=10, b=20;
int *const p=&a;	// 只能初始化来赋值
p = &b;	// 错误,p是只读的
p = p;	// 错误,p是只读的
p++;	// 错误,p是只读的
*p = 2019;	// 正确

第18讲:指针与数组

  1. C++规定,数组名既代表数组本身,又代表整个数组的地址,还是其首个元素的地址值。数组名为常量。
  2. 指针的基类型应与其指向的对象的类型一致。
  3. C++扩充了对象的访问方式——引用访问。
  4. 引用即一个对象的别名,均为const类型,其声明形式为引用类型 &引用名称=对象名称
  5. 引用必须初始化,且不能引用有效内存对象;一旦初始化后不能改变引用关系;指定类型的引用不能初始化到其他类型的对象上;引用初始化与对引用的赋值含义完全不同。
int &r;	// 未初始化,错误
int x, &ref=x, y;	// 正确
int &ref = y;	// 错误
//*******//
int x;
int &r=x;	// 初始化,r为x的引用
r = 100;
//******//
int x, &r=x;
int *p1=&x;	// p1指向x
int *p2=&r;	// p2指向r,本质上指向x

第19讲:指针与函数

  1. C++扩充引用类型主要是为了扩充函数形参的类型,由此函数参数传递增加为三种方式:传递对象本身,传递对象的指针,传递对象的引用(此方法比使用指针作为函数参数更加清晰、简洁)。
#include
using namespace std;
void swap(int &a, int &b){
    int t;
    t = a;
    a = b;
    b = t;
}
int main(){
    int x=3, y=4;
    swap(x,y);
    cout<<x<<","<<y<<endl;

    return 0;
}
  1. 函数返回引用即返回传入的实体本身,因此函数返回的引用可以作为左值
#include
using namespace std;
// 函数返回指针,将其解引用后作为左值
int *fun1(int *a, int *b){
    return (*a>*b)?a:b;
}
// 函数返回引用,直接作为左值
int &fun2(int &a, int &b){
    return a>b?a:b;
}
int main(){
    int x=3, y=4;
    cout<<x<<","<<y<<endl;
    *fun1(&x, &y) = 5;
    cout<<x<<","<<y<<endl;
    fun2(x, y)=6;
    cout<<x<<","<<y<<endl;

    return 0;
}
  1. C++规定函数入口地址为函数的指针,即函数名既代表函数又代表函数的指针(地址)。【由此感悟到程序功能的本质是操作存储器上由地址标识的数据】
#include
using namespace std;
int *fun1(int *a, int *b){
    return (*a>*b)?a:b;
}
int main(){
    int x=3, y=4, z;
    int *(f)(int *, int *)=fun1(int *, int *);	 // 错误,不能像变量一样给函数初始化
    
    // 函数的引用,即别名,函数名即函数指针,调用时需解引用
    int *(&fun)(int *, int *)=fun1; 	
    // 函数的指针,调用时需解引用
    int *(*funp)(int *, int *)=fun1;	
    
    z = *fun(&x, &y);
    cout<<x<<","<<y<<endl<<z<<endl;
    x = 5;
    z = *funp(&x, &y);
    cout<<x<<","<<y<<endl<<z<<endl;

    return 0;
}
  1. 函数指针常用于动态地调用返回值类型相同的不同函数,例如求定积分的函数。

你可能感兴趣的:(C++语言)