【学习笔记 Day04】C++基础:独一份的指针,探索其中的奥秘!

数组、指针与字符串

数组

数组是具有一定顺序关系的若干对象的集合体,组成数组的对象被称为该数组的元素。

每个元素有 n 个下标的数组被称为 n 维数组。

声明一个数组类型,应该包括以下几个方面:

  1. 确定数组的名称
  2. 确定数组元素的类型
  3. 确定数组的结构(包括数组维数,每一维的大小等)

声明语法:数据类型 标识符[常量表达式1][常量表达式2]...

例如:

int b[5];
int b[] = {1,2,3};

int a[5][5];
int a[][] = {{1,2,3},{1,2,3},{1,2,3}};

数组的使用:数组名[常量表达式1][常量表达式2]...

数组的存储:数组元素在内存中是顺序的、连续存储的。

数组的初始化:在声明数组时给部分或全部元素赋初始值。

注意:

  1. 如果数组后面没赋值的,则默认为0
  2. 在多维数组中,[][] 的顺序时先行后列的
  3. 在定义方法的形参中,二维数组中的列大小不能省略
void rowSum(int a[][3])
{
      //...
}

void main()
{
      int table[4][3]={...};
      rowSum(table);
}

对象数组

数组的元素不仅可以是基本数据类型,也可以是自定义类型。

声明语法:类名 数组名[常量表达式]

使用:数组名[下标表达式].成员名

指针

指针变量是用于存放内存单元地址的。

声明语法:数据类型 *标识符

与地址相关的运算:

  1. *:称为指针运算符
  2. &:称为取地址运算符
int *p;

cout << *p << endl;//输出指定所指向的内容

int a,b;
int *pa, *pb = &b;
pa = &a;

指针的赋值:

  • 定义语法:存储类型 数据类型 *指针名 = 初始地址;
  • 赋值语法:指针名 = 地址;

注意:

  • 一个数组,可以用它的名称来直接表示他的初始地址。数组名实际上就是一个不能被赋值的指针,即指针常量。
void main()
{
      int i;
      int *p = &i;
      i = 10;
      cout << i << endl;  //输出int类型的数的值
      cout << *p << endl; //输出int类型指针所指地址的内容
}
  • 可以声明指向常量的指针,此时不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。
  • 可以声明指针类型的常量,这时指针本身的值不能被改变。
  • 一般情况下,指针的值只能赋给相同类型的指针。,但是有一种特殊的 void 类型指针,可以存储任何类型的对象地址。

指针的运算:

  • *p1+n1(*(p1+n1)/p1[n1]):表示p1当前所指位置后方第n1个数的地址
  • *p1-n1(*(p1-n1)/p1[-n1]):表示p1当前所指位置前方第n1个数的地址
  • *p++/*p–:表示指针当前所指位置下一个或前一个数据的地址
  • 空指针:可以用 NULLnullptr 来表示

指针数组

如果一个数组的每一个元素都是指针变量,这个数组就是指针数组。

注意:指针数组存储的是变量的地址!

void main()
{
      int arr1 = {1,2,3}
      int arr2 = {1,2,3}
      int arr3 = {1,2,3}
      
      int *pArr[3] = {arr1,arr2,arr3};
      
      for(int i = 0;i<3;i++)
      {
            for(int k = 0;k<3;k++)
            {
                  //pArr存储的是指针地址
                  cout << pArr[i][j] << endl;
            }
      }
}

指针型函数:

除了 void 类型函数外,函数在调用结束之后都要有返回值,指针也可以是函数的返回值。

指针函数的语法:

返回值的数据类型 *函数名(参数列表)
{
      函数体;
} 

函数返回数组指针:由于数组不能被复制,因此函数不能返回数组,但是可以返回数组的指针。

语法:

类型说明符 (*函数名(参数列表))[数组维度]

//(*函数名(参数列表)):意味着对函数返回的结果执行解析操作

例如:

typedef int arr[10];
//foo 返回一个指向含有10个整数的数组的指针
arr* foo(int i);

//或

int (*foo(int i))[10]

C++ 11标准中提供了一种可以简化上述 foo 声明的方法,即使用尾置返回类型。任何函数的定义都可以使用尾置返回类型,但是这种形式对于返回类型复杂的函数更有效。

语法:auto 函数名(参数列表) -> 类型说明符(*)[数组维度]

例如:

auto foo(int i) -> int(*)[10];

如果知道函数返回的指针将只想哪一个数组,就只可以使用 decltype 关键字声明返回类型。

例如:

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

decltype(a) *func(int i)
{
      return (i%2)? &a :&b;
}

指向函数的指针

注意:声明一个函数指针时,也需要说明函数的返回值、形式参数列表!

语法:

数据类型 (*函数指针名)(形参表)

//说明类型:说明函数指针所指函数的返回值类型

例如:

int (*foo)(int i);

函数指针在使用之前也要进行赋值,使指针指向一个已经存在的函数代码的地址。

语法:

函数指针名 = 函数名;

例如:

void float printStuff(float data)
{
      cout << "printStuff" << endl;
}

void printMessage(float data)
{
      cout << "printMessage" << endl;
}

void printFloat(float data)
{
      cout << "printFloat" << endl;
}

const float PI = 3.1415926f;
const float Two_PI = 3.1415927f;

void main()
{
      void (*func)(float);
      
      printStuff(PI);
      func = printStuff;              //函数指针指向 printStuff
      func(PI);                       //通过函数指针进行调用
      func = printMessage;            //函数指针指向 printMessage
      func(Two_PI);
      func(13.0);
      func = printFloat;
      fun(PI);
}

对象指针

对象指针用于存放对象地址的变量。

语法:

类名 *对象指针名

//使用
对象指针名 -> 成员名
//或
(*对象指针名).成员名

例如:

Point *p;
Point p1;
p = p1;

this 指针

this 指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包括构造函数和析构函数),它用于指向正在被成员函数操作的对象。

指向类的非静态成员的指针

指向对象成员的指针使用前也需要先声明,再赋值,然后在引用。

语法:

类型说明符 类名::*指针名;             //声明指向数据成员的指针
类型说明符 (类名::*指针名)(参数列表);  //声明指向函数成员的指针

声明了指向成员的指针之后,需要对其进行赋值,语法:

指针名 = &类名::数据成员名;

访问数据成员时,可以使用以下语法:

对象名.*类成员指针
//或
对象指针名 -> *类成员指针名

访问函数成员时,可以使用以下语法:

(对象名.*类成员指针名)(参数列表);
//或
(对象名 -> *类成员指针名)(参数列表);

指向类的静态成员的指针

对类的静态成员的访问是不依赖于对象的。

动态内存分配

运算符 new 的功能是动态分配内存或称为动态创建堆对象。

创建对象的语法:

数据类型 变量名 = new 数据类型(初始化参数列表);

建立和删除堆对象使用两个运算符: new 和 delete(两两配合使用,不然会内存泄漏)。

删除对象的语法:

delete 指针名;

例如:

int *point = new int(2);

delete *point;

使用 vector 创建数组对象

vector 不是一个类,而是一个类模板。

语法:

vector<元素类型> 数组对象名(数组长度,元素初值);

//访问数组:
数组对象名[下标索引位置];

例如:

vector<int> arr(10);

arr[5];

字符串

string 类提供了对字符串进行处理所需要的操作。

  • 构造函数的原型:
//默认构造函数,建立一个长度为0的字符串
string();
//复制构造函数
string(const string &rhs);
//用指针s所指向的字符串常量初始化string类的对象
string(const char *s);
//将对象 rhs 中的串从位置pos开始取n个字符,用来初始化string类的对象。
string(const string &rhs,unsigned int pos,unsigned int n);
//注:串中的第一个字符的位置为0
//用指针s所指向的字符串中的前n个字符初始化string类的对象
string(const char *s,unsigned int n);
//将参数c中的字符重复n次,用来初始化string类的对象
string(unsigned int n,char c);
  • string类的操作符
操作符示例注释操作符示例注释
+s+t将串s和t连接成一个新串<s<t判断s是否小于t
=s=t用t更新s<=s<=t判断s是否小于或等于t
+=s+=t等价于s=s+t>=s>=t判断s是否大于等于t
==s==t判断s与t是否相等>s>t判断s是否大于t
!=s!=t判断s与t是否不相等[]s[i]访问串中下标为i的字符
  • 常用成员函数功能简介
//将字符串s添加到本字符串的末尾
string append(const char *s);

/赋值:将s所指向的字符串赋值给本对象
string assign(const char *s);

//比较本串与str串的大小,当本串小于str串时,返回复数,反之返回正数,两串相等时返回0
int compare(const string &str) const;

//将s所指向的字符串插入在本串中的位置p0之前
string &insert(unsigned int p0,const char *s);

//取子串,取本串中的位置pos开始n个字符,构成新的string类对象作为返回值
string substr(unsigned int pos,unsigned int n) const;

//查找并返回str在本串中第一次出现的位置
unsigned int find(const basic_string &str) const;

//返回串的长度(字符个数)
unsigned int length() const;

//将本串与str中的字符串进行交换
void swap(string &str);

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容