文章目錄
-
- 第13講:數組的定義和使用
- 第14講: 數組與函數
- 第15講:字元串的處理
- 第16講:數組的應用
- 第17講:指針的定義與使用
- 第18講:指針與數組
- 第19講:指針與函數
第13講:數組的定義和使用
- 一維數組的定義、記憶體形式(連續存儲)、初始化。
- 靜态數組與動态數組的初始值。
- 二維數組的定義、記憶體形式(按行連續存儲)、初始化。
- 多元數組的引用。
第14講: 數組與函數
- 數組元素作為函數參數。
- 整個數組作為函數參數,傳遞的是數組的首位址,是以實參和形參為同一個對象。
- 數組作為函數參數時,編譯器不檢查數組的長度,是以将數組的首位址傳入函數時,常需傳入另一個參數來表示實參數組的長度。但是多元數組除第一維外其餘維數的長度不可省略,否則無法确定數組的基類型。
第15講:字元串的處理
- 編譯器在編譯字元串常量時自動在其末尾加上結束符
。'\0'
- 【字元串處理函數】
- 【字元串對象】:其類在
頭檔案裡定義,字元串對象不需結束符string
,且采用動态記憶體管理,還會檢查記憶體越界。\0
- 字元串對象可用字元串常量直接進行指派而不需調用字元串處理函數。
- 字元串對象的操作:指派運算、連接配接運算、關系運算。
第16講:數組的應用
- 用數組解決排序問題:交換排序、選擇排序。
- 用數組解決查找問題:順序查找、二分查找。
- 【二分查找執行個體】:
#include <iostream>
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講:指針的定義與使用
- 資料的寫入與讀出均與記憶體打交道,而指針類型就是處理記憶體位址的資料類型。指針不僅能提高程式的效率,而且能使一個函數通路另一個函數的局部變量,是以指針是函數進行資料交換必不可少的工具。
- 程式中的資料對象在生命周期内總是占用一定的存儲空間,有确定的存儲位置。按對象名稱存取對象為直接通路,通過指針存取對象為間接通路。
- 由于指針的特殊性,指針的初始化和指派是受一定限制的,隻能是以下四種值:
- 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; // 正确
- 基類型相同的指針變量的值
- 對象存儲空間的下一個有效位址
- 【指針的有效性】:指針指向有确定存儲空間的對象時為有效指針,否則為無效指針。
- 【無效指針】:0值指針(空指針);未初始化、未指派或運算後指向未知對象的指針;指向對象被釋放後值卻未變的指針。
- 【指針運算】:指針作用在連續存儲空間上才有意義,比如指針加減整數、同類型指針相減、指針間的關系運算。
- 【指針的限定】:
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=π // 錯誤,p非const指針
const double *ptr=π // 正确,ptr為const型指針
- 允許把非
對象的位址賦給const
基類型的指針變量,但不可通過const
基類型的指針改變其所指的非const
對象的值。const
常用于函數形參以保護限定實參為隻讀,此舉可增加程式健壯性。const基類型的指針
const double pi=3.14;
const double *p=π // 正确
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講:指針與數組
- C++規定,數組名既代表數組本身,又代表整個數組的位址,還是其首個元素的位址值。數組名為常量。
- 指針的基類型應與其指向的對象的類型一緻。
- C++擴充了對象的通路方式——引用通路。
- 引用即一個對象的别名,均為
類型,其聲明形式為const
。引用類型 &引用名稱=對象名稱
- 引用必須初始化,且不能引用有效記憶體對象;一旦初始化後不能改變引用關系;指定類型的引用不能初始化到其他類型的對象上;引用初始化與對引用的指派含義完全不同。
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講:指針與函數
- C++擴充引用類型主要是為了擴充函數形參的類型,由此函數參數傳遞增加為三種方式:傳遞對象本身,傳遞對象的指針,傳遞對象的引用(此方法比使用指針作為函數參數更加清晰、簡潔)。
#include<iostream>
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;
}
- 函數傳回引用即傳回傳入的實體本身,是以函數傳回的引用可以作為左值。
#include<iostream>
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;
}
- C++規定函數入口位址為函數的指針,即函數名既代表函數又代表函數的指針(位址)。【由此感悟到程式功能的本質是操作存儲器上由位址辨別的資料】
#include<iostream>
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;
}
- 函數指針常用于動态地調用傳回值類型相同的不同函數,例如求定積分的函數。