「C++程序设计笔记」第六章 数组,指针与字符串(一)

第六章 数组,指针与字符串(一)

数组的定义与初始化

数组的定义与使用

如:int a[10];

int a[5][3];
二维数组

a[0] = a[5] + a[7];

数组的存储与初始化

元素间物理地址上的相邻,对应着逻辑次序上的相邻。

数组名是数组首元素的内存地址。是常量;

一维数组的初始化

列出全部元素的初始值

    `static int a[10] = {0,1, 2, 3, 4, 5, 6, 7, 8, 9};`

只给部分元素指定初始值
 
    `static int a[10] = {0, 1, 2, 3, 4};`

还可以不指定长度
     
    `static int a[] = {0, 1, 2, 3,4, 5}`
二维数组的存储

按行列存储

  • 初始化

      将所有初始值写在一个{}内,按顺序初始化;
    
      分行列出二维数组元素的初值;
      
      `static int a[3][4] = {{1, 3, 4, 5}, {1,2}, {2213,43,3}}`
    

第一维下标个数可省略

二维数组的初始化

如果不做初始化,局部作用域的非静态数组中会存在垃圾数据,static数组中的数据默认初始化为0;

如果只对部分元素初始化,剩下的未显示初始化的元素,将自动被初始化为零;

数组作为函数的参数

数组元素做不了形参;

数组名做参数,形,实参数都应该是数组名,类型要一样,传送的是数组首地址。对形参数组的改变会直接影响到实参数组。

将数组做函数参数时,在函数体内对形参数组数据的修改将会直接影响实参数组

对象数组

只要对象都属于同一种类型就可以了

数组元素的构造和析构

构造数组时,元素所属的类未声明构造函数就用默认构造函数;

各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。

各元素对象的初值要求为不同值时,需要声明带形参的构造函数。

当数组中每一个对象被删除时,系统要调用一次析构函数。

基于范围的for循环
int main()
{
    int array[3] = {1, 3, 4};
    for(int& e:array)
    {
        e+=2;
        cout << e << endl;
    }
    return 0;
}

指针的概念、定义和指针运算

内存空间的访问方式:
通过变量名访问;

通过地址访问;
指针的概念
指针:内存地址,用于简介访问内存单元

指针变量:用于存放地址的变量

指针运算过程就是寻址过程;

指针变量的初始化和赋值

如int* pa = &a;

可以用一个已有合法值的指针去初始化另一个指针变量。

不要用一个内部非静态变量去初始化static指针。
指针变量的赋值运算

指针名=地址;

地址如:

通过地址运算“&”求得已定义的变量和对象的起始地址

动态内存分配成功时返回的地址;

整数0可以赋值给指针,表示空指针

允许定义或声明指向void类型的指针。该指针可以被赋予任何类型对象的地址;
但是,只能存放地址而不能用它访问它所指向的对象(内存空间)

int *pint = static_cast<int *>(pv); //void指针转换为int指针
指针空值nullptr

c++11中,使用nullptr关键字,使得表达更准确,指针运算更安全;

指向常量的指针

const指针;

int a;
const int* p = &a; //p是指向常量的指针
int b;
p = &b; //正确,p本身的值可以改变
*p = 1; //编译时出错,不能通过p改变所指的对象;

也可以将指针本身定义成常量;

int a; int* const p = &a;

指针的算术运算、关系运算
指针类型的算术运算

指针p加上或减去n

意义是指针当前指向位置的前方或后方第n个数据的起始位置。

    比如一个int对象占4个字节,它就应当指向首字节;
++, --运算也同样是完整数据的移动;

当指针指向连续存储的同类型数据时,指针与整数的加减运算和自增自减才有意义;

short a[4];
short *pa = a;
// *pa等同于a[0]
// *(pa+n)等同于a[n], 
// 一次进两个字节
指针类型的关系运算
指向同类型数据的指针之间可以进行各种关系运算。

指向不同数据类型的指针,以及指针与一般整数变量之间的关系预算是无意义的;

指针可以和零之间进行等于或不等于的关系运算:

    例如:p==0或p!=0;

指针与数组

指针访问数组元素

pa=&a[0]; 或 pa=a;

pa就是a[0],(pa+1)就是a[1],… ,*(pa+i)就是a[i].
a[i], *(pa+i), *(a+i), pa[i]都是等效的。

不能写a++,因为a是数组首地址、是常量。

指针数组:数组元素是指针类型

利用指针数组存放矩阵:

#include 
using namespace std;
int main() {
	int line1[] = { 1, 0, 0 };	//矩阵的第一行
	int line2[] = { 0, 1, 0 };	//矩阵的第二行
	int line3[] = { 0, 0, 1 };	//矩阵的第三行
	
	//定义整型指针数组并初始化
	int *pLine[3] = { line1, line2, line3 };	
	cout << "Matrix test:" << endl;
  //输出矩阵
	for (int i = 0; i < 3; i++) {
	  for (int j = 0; j < 3; j++)
	    cout << pLine[i][j] << " ";
    cout << endl;
	}
	return 0;
}
输出结果为:

Matrix test:

1,0,0

0,1,0

0,0,1
指针与函数

传指针也是引用传递的一种;

为什么要用?

需要数据双向传递时(引用也可以达到此效果)

需要传递一组数据,只传首地址运行效率比较高;

例:

#include <iostream>
using namespace std;
void splitFloat(float x, int *intPart, float *fracPart) {
   *intPart = static_cast<int>(x); //取x的整数部分
   *fracPart = x - *intPart; //取x的小数部分
}
int main() {
  cout << "Enter 3 float point numbers:" << endl;
  for(int i = 0; i < 3; i++) {
    float x, f;
    int n;
    cin >> x;
    splitFloat(x, &n, &f);	//变量地址作为实参
    cout << "Integer Part = " << n << " Fraction Part = " << f << endl;
  }
  return 0;
}

指向常量的指针做形参

#include <iostream>using namespace std;
const int N = 6;
void print(const int *p, int n);
int main() {
  int array[N];
  for (int i = 0; i < N; i++)
        cin>>array[i];
  print(array, N);
  return 0;
}
void print(const int *p, int n) {
  cout << "{ " << *p;
  for (int i = 1; i < n; i++)
        cout << ", " << *(p+i);
  cout << " }" << endl;
}
指针类型的函数

返回值是指针;

存储类型 数据类型 *函数名()

{ //函数体语句

}

注意事项:

不要将非静态局部地址用作函数的返回值。

错误的例子:

在子函数中定义局部变量后将其地址返回给主函数,就是非法地址。

正确的例子:

主函数中定义的数组,在子函数中对该数组元素进行某种操作后,
返回其中一个元素的地址,这就是合法有效的地址。

在子函数中通过动态内存分配new操作取得的内存地址返回给主函数
是合法有效的,但是内存分配和释放不在同一级别,要注意不能忘记
释放,避免内存泄漏。
指向函数的指针

为什么需要?

通过函数指针调用的函数

例如将函数的指针作为参数传递给一个函数,使得在处理相似事件的时候可以灵活的使用不同的方法。

调用者不关心谁是被调用者

需知道存在一个具有特定原型和限制条件的被调用函数。
函数指针举例

对象指针

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值