day03.C++函数与指针(含new与delete关键字,函数指针,指针函数,指针数组)

一.指针

#include<iostream>
using namespace std;
#define pi 3.14159//定义常量

int main(){
    cout<<pi<<endl;
    int a=10;
    int *p=NULL;//定义指针
    p=&a;
    cout<<"a的地址为:"<<p<<endl;
    cout<<"a="<<*p<<endl;
    return 0;
}

1.指针的作用

通过指针可以间接访问内存

  • 内存编号是从0开始记录的,一般用十六进制数字表示。
  • 可以利用指针变量保存地址。

2.指针的定义与使用

语法:数据类型 * 变量名。  int *p;

(1)一级指针:

<1>.定义,赋值与输出:
#include<iostream>
using namespace std;
int main()
{
	int a=10,b=11;
	int *p=&a;
    int *t=NULL;//定义一个指针
    t=&b;//&取地址
	cout<<"指针t:"<<*t<<endl<<"b的地址:"<<&b<<endl<<"b="<<b<<endl;
	return 0;
}

(2)二级指针

<1>.二级指针的定义,赋值与输出
#include<iostream>
using namespace std;
int main()
{
	int a=10;
	int *p=&a;
	int **pp=&p;
	cout<<"*p:"<<*p<<endl<<"&a:"<<&a<<endl<<"a:"<<a<<endl<<"**pp:"<<**pp<<endl<<"&pp:"<<&pp<<endl<<"&p:"<<&p;
	return 0;
}

*p:10
&a:0x6ffdfc
a:10
**pp:10
&pp:0x6ffde8
&p:0x6ffdf0

#include <iostream>
using namespace std;
int main()
{
    int i = 9, t = 10, k = 11;
    int *p = &i;
    int *m = &i;     // 一级指针p,m
    int **pp = &p;
    int **mm = &m; // 二级指针pp,mm
    cout << "一级指针*p=" << *p << endl
         << "二级指针**pp=" << **pp << endl;
    cout << "一级指针*m=" << *m << endl
         << "二级指针**mm=" << **mm << endl;
    cout << "修改一级指针的内容后:" << endl;
    *p = t;
    cout << "一级指针*p=" << *p<< endl
         << "二级指针**pp=" << **pp << endl;
    cout << "修改一级指针的指向后:" << endl;
    *mm=&k;
    cout << "一级指针*m=" << *m << endl
         << "二级指针**mm=" << **mm << endl;
    return 0;
}

<2>.二级指针的步长:

所有类型的二级指针,由于均指向一级指针类型,并且所有一级指针类型大小是 4,

所以二级指针的步长也是 4。
<3>.改变n-1级指针的指向:

    可以通过一级指针,修改 零级指针(变量)的内容。
    可以通过二级指针,修改一级指针的指向。
    可以通过三级指针,修改二级指针的指向。

    可以通过四级指针,修改三级指针的指向。
     ·····
    可以通过修改 n  级指针,从而间接修改 n-1  级指针的指向。

3.空指针与野指针

空指针: 指针变量指向内存中编号为0的空间

用途: 初始化指针变量

注意: 空指针指向的内存是不可以访问的


int *p = NULL;//初始化指针,NULL为0
//空指针不可访问
//0~255之间的内存编号是系统占用的,不允许用户访问
cout << *p << endl;// 引发了异常: 读取访问权限冲突。p 是 nullptr。

野指针: 指针变量指向非法的内存空间

4.关键字new与delete【动态内存管理】⭐️

(1)作用:

使用new与delete管理对象,new分配内存,delete释放内存。

在C++提供关键字new来创建对象,delete释放对象,但释放数组需要加上[]。

(类似于:在C语言是用库函数malloc来申请内存,free来释放内存)。

                                                       动态管理内存的入口
malloc,     freenew,   delete
C/C++标准库的函数C++操作符
只是动态分配内存空间/释放空间除了分配空间还会调用构造函数和析构函数进行初始化与清理(清理成员)
需要手动计算类型大小且返回值w为void可自动计算类型的大小,返回对应类型的指针。
管理内存失败会返回0方式管理内存失败会抛出异常
#include<iostream>
using namespace std;
int main(){
    int *p1=new int;
    *p1=99;
    cout<<"sizeof *p1="<<sizeof(*p1)<<endl;
    cout<<"*p1="<<*p1<<endl;
    cout<<"p1="<<p1<<endl;
    delete p1;//释放p1指向的内存
    return 0;
}

这将释放p指向的内存,但不会删除指针p本身。例如,可以将p重新指向另一个新分配的内存块。

一定要配对地使用new和 delete否则将发生内存泄漏(memory leak),也就是说,被分配的内存再也无法使用了。如果内存泄漏严重,则程序将由于不断寻找更多内存而终止。

(2)使用:

    <1>int *p1 = new int[10];   
          返回一个指向int型的指针int*  

   <2> int (*p2)[10] = new int[2][10];
         返回一个,指向int[10]这样的一维数组的,指针int (*)[10]

   <3> int (*p3)[2][10] = new int[5][2][10];     

          返回一个指向二维数组int[2][10]这种类型的指针int (*)[2][10]


#include<iostream>
using namespace std;
int mian(){
    //定义一个指针:
    int *p1=new int;//动态分配指针
    *p1=3;//单独赋值
    int *p2=new int(8);//初始化,在new后面直接赋值

    //定义一个数组时,同样用一个指针指向数组的首地址
    int *p3=new int[5];//动态分配指针数组
    for(int i=0;i<5;i++)p3[i]=i;
    
     delete p1;
     delete p2;
     delete[] p3;
     
     return 0;
}

5.指针与数组

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

指针指向数组:  int *p=a;

(1)普通遍历数组:

int i, a[9];
for(int i=0;i<9;i++)
a[i]= i;
for (i = 0; i <= 9; i++)
{
    std::cout << a[i]<< std::endl;
}

(2)用指针遍历数组:

int i, a[9];
for(int i=0;i<9;i++)
a[i]= i;
for (i = 0; i <= 9; i++)
{
    std::cout << *(a+i)<<std::endl;
}

(3)用指针访问遍历数组:

int i, a[9],*pa;
for(int i=0;i<9;i++)a[i]= i;
pa=a;
for (i = 0; i <= 9; i++)
{
    std::cout << pa[i]<<std::endl;
}
#include<iostream>
using namespace std;
int main(){
    int i=0,a[4],*pa;
    for(i=0;i<4;i++)a[i]=i;
    pa=a;
    for(i=0;i<4;i++)cout<<*pa++<<endl;
     return 0;
}

   6.指针数组

指针数组:char *pa[10];

#include <iostream>
using namespace std;
int main()
{
	char * pArray[] ={"apple","pear","banana","orange","grape"};
	for(int i=0; i<sizeof(pArray)/sizeof(*pArray); i++)
		cout << pArray[i] << endl;

	return 0;
}

二.函数

#include<iostream>
using namespace std;
void max(int p,int t);//函数声明
int main(){
    int a=9,b=10;
    cout<<a<<b<<endl;
    max(a,b);//函数调用,实参列表
    return 0;
}
void max(int p,int t){//函数定义,形参列表
     int u=p>t?p:t;
     cout<<u<<endl;
}

形参与实参的关系:
两者是在调用的时候进行结合的,通常实参会取值传递给形参,形参之后进行函数过程运算,然后可能将某些值经过参数或函数符号返回给调用者。 

"值传递"是单向传递,由实参传向形参,如果形参发生改变,不会影响实参。

1.文件包含

文件包含是指将一些头文件或其他源文件包含到本文件中,一个文件被包含后该文件的所有内容就被包含进来了。
#include<文件名>
#include"文件名"

尖括号< >和双引号" "的区别:

  1. 用尖括号时,称为标准模式,系统直接到存放c/c++库函数的文件中查找要包含的文件。
  2. 用双引号的时候,系统优先在当前目录中查找要包含的头文件,若找不到,再按标准模式查找。

一般来说,使用库函数的时候用< >使用用户自定义的头文件时用" ";

2.指针作为函数形参

实参会地址传递给形参

”地址传“: 指针作为形式参数,可以接受实参传来的值,同时可以修改实参的值。

(地址传递中形参改变,对应的实参也会发生改变。)

#include <iostream>
using namespace std;
 void swap(int *p,int *t){
    int temp=*p;
    *p=*t;
    *t=temp;
 }
int main()
{
    int a=10,b=20;
    swap(&a,&b);
    cout<<a<<endl<<b;	
	return 0;
}

3.指针函数

(1)指针函数的定义

“指针函数”的定义: 一个返回类型为指针的函数。

注:

  1. 指针函数的本质是函数。
  2. 只是其返回值是一个某某类型的指针,是一个地址。

(2)指针函数的声明

#include<iostream>
using namespace std;
int *pfun(int a,int b);//声明指针函数pfun

int main(){
    int *p=NULL;
    p=pfun(5,3);//调用指针函数
    cout<<*p<<endl;
    free(p);
    return 0;
}
int *pfun(int a,int b){//指针函数
    int *p=(int *)malloc(sizeof(int));
    *p=a-b;
    return p;
}

输出:2

4.函数指针

(1)函数指针的定义

”函数指针“的定义:是一个指向函数的指针变量。

注:

  1. ”函数指针“本质上是一个指针变量。
  2. 函数指针就指向函数的入口地址,可以通过函数指针来调用函数。(C语言中每一个函数都有一个入口地址)

(2)函数指针的声明方法

int FUNC(int x);  	//声明一个函数FUNC
int (*fun)(int x,int y);  //声明一个函数指针 
fun = FUNC;  			// 将FUNC函数的首地址赋给指针fun 
fun=&FUNC//将函数地址赋值给函数指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/376395.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python函数入参、类成员引用支持灵活参数可配

一、背景 python编码时&#xff0c;有可能在不同场景下输入修改的参数&#xff0c;不方便直接写死&#xff0c;因此需要灵活配置这些函数入参&#xff0c;类成员 二、函数入参支持灵活可配 场景&#xff1a;如下场景&#xff0c;对于hello函数&#xff0c;不同场景下想要对不…

如何修改远程端服务器密钥

前言 一段时间没改密码后&#xff0c;远程就会自动提示CtrlAltEnd键修改密码。但我电脑是笔记本&#xff0c;没有end键。打开屏幕键盘按这三个键也没用。 解决方法 打开远程 1、远程端WINC 输入osk 可以发现打开了屏幕键盘 2、电脑键盘同时按住CtrlAlt&#xff08;若自身电…

学习Spring的第十六天

AOP底层两种生成Proxy的方式 我来解释这两种方式 1 目标类有接口 , 调用JDK的动态代理实现 2 目标类没有接口 , 用Cglib实现 , 即生成目标类的子类 , 来实现动态代理 , 所以要求目标类不能时final修饰的 . (若有接口 , 也可用Cglib方式实现 , 需要手动配置<aop: config pr…

java设计模式- 建造者模式

一 需求以及实现方式 1.1 需求描述 我们要创建一个表示汽车的复杂对象&#xff0c;汽车包含发动机、轮胎和座椅等部分。用传统方式创建&#xff0c;代码如下 1.2 传统实现方式 1.抽象类 public abstract class BuildCarAbstaract {//引擎public abstract void buildEng…

Swift Combine 管道 从入门到精通三

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二 1. 用弹珠图描述管道 函数响应式编程的管道可能难以理解。 发布者生成和发送数据&#xff0c;操作符对该数据做出响应并有可能更改它&#xff0c;订阅者请求并接收这些数据。 这…

Python程序员面试题精选(1)

本文精心挑选了10道Python程序员面试题&#xff0c;覆盖了Python的多个核心领域&#xff0c;包括装饰器、lambda函数、列表推导式、生成器、全局解释器锁(GIL)、单例模式以及上下文管理器等。每道题都附有简洁的代码示例&#xff0c;帮助读者更好地理解和应用相关知识点。 题目…

Python模拟点赞助手

背景 之前公司一直会安排各种学习任务&#xff0c;视频章节很多的视频&#xff0c;有些是技术的有些是政策相关的&#xff0c;如果没有按时完成学习任务会被通报。但是&#xff0c;这些学习内容不一定有帮助&#xff0c;所以大家就养成了刷课的习惯&#xff0c;也就是点开视频…

服务器运存使用率多少正常?

服务器运存使用率多少正常&#xff0c;这是一个相对主观的问题&#xff0c;因为服务器的正常运行不仅取决于运存使用率&#xff0c;还与服务器的工作负载、应用程序的特性和需求、服务器的配置和用途等多种因素有关。然而&#xff0c;一般来说&#xff0c;大多数服务器在运存使…

###C语言程序设计-----C语言学习(10)#函数再探

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 基础知识的学习 1.不返回结果函数 2.局部变量 3.全局变量 4.…

AIGC ChatGPT4 实战案例教你VLOOKUP用法

实际需求&#xff1a; 像这样的案例可以通过VLOOKUP来完成&#xff0c;如果不会使用VLOOKUP也没有关系&#xff0c;我们可以先让ChatGPT来帮我们介绍一下VLOOKUP函数的具体用法。 VLOOKUP是Excel中的一个非常有用的函数&#xff0c;用于查找和检索数据。"V"在VLOOKUP…

Java面向对象 this

this 在Java中&#xff0c;this 是一个特殊的引用变量&#xff0c;它引用了当前对象实例。当在类的非静态方法或构造方法中使用时&#xff0c;this 关键字指代当前的对象实例。它经常用于区分对象的成员变量和局部变量&#xff0c;或者调用其他重载的方法。 以下是一些使用 t…

锁(二)队列同步器AQS

一、队列同步器AQS 1、定义 用来构建锁或者其他同步组件的基础框架&#xff0c;它使用了一个int成员变量表示同步状态&#xff0c;通过内置的FIFO队列来完成资源获取线程的排队工作。是实现锁的关键。 2、实现 同步器的设计是基于模板方法模式的&#xff0c;也就是说&#…

Ubuntu22.04切换系统cuda版本

由于最近项目要求的cuda版本有差异&#xff0c;而在Ubuntu中可以通过切换cuda来满足需求&#xff0c;现记录如下。 1、按照 Ubuntu22.04与深度学习配置 中的cuda安装章节&#xff0c;将需要的cuda版本下载到本地并进行安装。 2、cuda安装完成后修改bashrc文件内容 sudo gedit …

Spring核心基础:全面总结Spring中提供的那些基础工具类!

内容概要 Spring Framework 提供了众多实用的工具类&#xff0c;这些工具类在简化开发流程、提升代码质量和维护性方面发挥了重要作用&#xff0c;以下是部分关键工具类的总结及其使用场景&#xff1a; StringUtils&#xff1a;不仅提供了基础的字符串操作&#xff0c;如拼接…

倍增c++

快速幂 区间最小值&#xff08;用倍增思想去求&#xff09; #include<bits/stdc.h> using namespace std; #define maxn 110000 #define ll long long int n, a[maxn], f[maxn][40]; int query (int l, int r) {int k (int)(log((r - l 1) * 1.0) / log(2.0));retur…

JWT令牌 | 一个区别于cookie/session的更安全的校验技术

目录 1、简介 2、组成成分 3、应用场景 4、生成和校验 5、登录下发令牌 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数据结构和算法&#xff0c;初步涉猎Pyth…

selenium+egdedriver+opencv 爬虫使用教程

一、Edge安装 二、Edge版本查看 1、安装内核要保证内核版本已浏览器版本一致 2、Window环境在edge浏览器中输入&#xff1a;edge://version/ 3、Ubuntu环境在浏览器目录执行 ./microsoft-edge-beta -verison 三、EdgeDriver安装 1、下载地址&#xff1a;https://developer.m…

iPhone 14支持NFC吗?如果支持,那么怎么启用

你准备好通过启用NFC来释放iPhone 14的全部潜力了吗&#xff1f;如果你曾经想知道如何在你的设备上利用NFC&#xff0c;那么你就来对地方了。 在本综合指南中&#xff0c;我们将引导你完成在iPhone 14上激活NFC的步骤&#xff0c;使你能够无缝连接其他设备&#xff0c;进行非接…

SpringSecurity(19)——OAuth2客户端信息存储

ClientDetailsService public interface ClientDetails extends Serializable {String getClientId();//客户端idSet<String> getResourceIds();//此客户端可以访问的资源。如果为空&#xff0c;则调用者可以忽略boolean isSecretRequired();//验证此客户端是否需要secr…

python 函数式编程入门:Lambda 函数的魅力

python 函数式编程入门&#xff1a;Lambda 函数的魅力 介绍Lambda 函数的应用排序过滤映射map、filter、reduce数据转换和筛选 介绍 Lambda 函数是 Python 中一个强大的功能&#xff0c;它可以快速创建匿名函数。在函数式编程中&#xff0c;lambda 函数发挥着至关重要的作用。…