c++-函数

news/2024/11/13 3:47:47/

c++-函数

  • 函数
    • 默认参数
    • 函数重载
  • 传递方式
    • 值传递
    • 指针(地址)传递
    • 引用传递
      • 引用传递与const
      • 指针引用
      • 引用与函数返回值
      • 引用与指针
      • 引用与临时数据 - 还要看
      • 引用与const 其他注意事项- 还没看
  • const 与函数
    • const与形参
    • const修饰函数(返回值)
    • const 成员函数
  • 内联函数 -- 还没看

函数

可以为函数多次声明,但是尽量不要这么做(后续的声明只能为之前哪些没有默认参数的值添加默认值)

默认参数

int b=2;
void func(int a=1,int c=b+2)
{}

注意:C++中在给定的作用域中只能指定一次默认参数
且编译器使用的是当前作用域中的默认参数

// 下面是在一个文件下同时进行声明和定义
// 下面通常来讲是错误的
void func(int a=1);int main()
{func();return 0;
}void func(int a=1) // 不能同时指定默认参数
{cout<<a<<endl;
}

第二个例子

这个例子就没有错误

/*test.c*/
void func(int a=1) // 定义的作用域在test.c文件中
{/*code*/cout<<a<<endl;
}
/*main.c*/
extern void func(int a=2); // 声明的作用域在main.c文件中
int main()
{func(); // a结果是2 不是1,编译器使用的是当前作用域中的默认参数return 0;
}

函数重载

函数功能类似,实现细节不同
函数名可以相同,参数列表不同(参数个数不同 或 参数类型不同 或 参数循序不同)就可以
编译器会自动根据实参类型进行调用
函数名必须相同,参数的返回值可以相同,也可以不相同

函数重载,本质上是不同的函数,占用不同的内存,入口地址不一样

注意:参数名不同不可以;参数名相同的情况下有缺省和无缺省 的重载不可以

注意:函数重载时的二义性问题(多个参数和类型转换的二义性),见文档

传递方式

内置数据类型,可以值传递、指针传递,引用传递没有必要(引用传递一般就是值传递)
数组必须是指针传递
结构体和实例对象可以值传递也可以指针传递

值传递

相当于深拷贝

指针(地址)传递

相当于浅拷贝

引用传递

c语言中没有引用传递
相当于别名
引用必须在定义的同时进行初始化,且不能在改变,即不能在引用其他数据

dataType &name=data;

对于指针
https://blog.csdn.net/llm_hao/article/details/108432323

typedef int * PINT;
PINT p1;
PINT &p2=p1; // p2是p1的别名

引用传递与const

对于自定义类型的参数(非内部类型)

/*在函数体内会产生自定义类型的临时对象用于赋值形参相当于深拷贝,这个临时(拷贝)对象的构造、复制、机构过程都消耗事件**需要注意的是,对于内部类型,int|float等形参,不存在构造、析构过程**
*/
void func(MyClass item){}  // 这个方法不会修改源数据// 可以改写为 引用传递的方式
void func(MyClass &item){} // 但是这个方法会修改源数据// 为了不修改源数据,又不消耗额外的内存
void func(const MyClass &item)

指针引用

注意事项: 地址传递的地址(地址)依然是副本(深拷贝、地址传递)
https://blog.csdn.net/llm_hao/article/details/108432323
https://blog.csdn.net/magicdoubi/article/details/98171260
通过地址(指针)传递可以修改指向的内容,但是指针本身是值传递
(当把一个指针作为参数传递给一个函数或方法时,其实是把指针的副本copy传递给了函数,即把指针的值本身传递到ptr,因此当在函数或方法内部修改指针(注意,不是修改指针所指向的值)时,其实修改的是函数内部指针的副本,而非外部的指针本身)
如果不是指针引用:指针的指向改变并不影响原指针的指向,指针指向的值的改变可以影响原值

进阶例子,看算法与数据结构dsa-单链表 - 重要

typedef struct LNode
{int data;struct LNode *next; // 用于指向下一个节点
}LNode,*LinkList; 
// typedef struct LNode NODE;
// typedef struct LNode *LinkList; // 下面其实是一样的,不过看起来更优雅
// LNODE * 表示一个节点,一个指向一个节点的指针
// LinkList 表示一个链表/* L1 相当是L的别名 而且是指针别名修改L1的指向,就是修改L的指向如果bool InitList(LinkList L1){}这样一开始形参(局部变量)L1和L指向的是同一块内存,但是L1=NULL后就指向的不是同一块内存了就是错误的
*/ 
bool InitList(LinkList &L1) // 引用传递
{L1=NULL; //struct LNode* ,这个必须是指针引用,否则,就不对return true;
}int main()
{LinkList L; // 相当于指针引用InitList(L);return 0;
}

引用与函数返回值

返回的是return 数据的别名
注意: 将引用作为函数返回值的时候,不能将局部数据的引用,因为局部数据存在栈区,函数调用结束后会被销毁,有可能下次使用数据的时候就不存在了

int &func(int &r)
{r+=10;return r;
}int main()
{int var=1;cout<<var<<endl; //1int var2=func(var); //11cout<<var<<endl; cout<<&var<<" "<<&var2<<" "<<&func(var)<<endl;cout<<var<<endl; // 21int &var3=func(var);cout<<var<<endl; //32cout<<&var3<<endl;// &var == &func(var)==&var3// &var != &var2return 0;
}

引用与指针

相同

引用就是对指针的封装,底层还是基于指针

int a=10;
int &a2=a;
cout<<&a2<<" "<<&a<<endl;// 在编译器下会被编译成
int a=10;
int *a2=&a;
cout<<a2<<" "<<&a<<endl;

区别

引用必须在定义时进行初始化,且不能被修改
指针可以被修改

数组必须是指针传递,不能使用引用传递(数组型字符串只能是指针,不能是引用) int &arr2[4]=arr1 没有这种写法
结构体和实例对象可以值传递也可以指针传递

引用++ 是数值+1
指针++ 是地址+1,指向下一个元素

引用与临时数据 - 还要看

见文档

引用不能指代临时数据
只有加上const 还是正确的

int m=10,n=20;// 下面都属于临时数据变量,不能被引用所指代,都是错的
int &a=m+n;
int &a=1+2;
int &a=2*3;
int &a=m+1;
int &a=func();void func(int &a) {}
func(m+n);
func(1+2);
func(m+1);// 下面是正确的
const int &a=m+n;
const int &a=1+2;
const int &a=2*3;
const int &a=m+1;
const int &a=func();void func(const int &a) {}
func(m+n);
func(1+2);
func(m+1);

引用与const 其他注意事项- 还没看

const 与函数

https://blog.csdn.net/u013377887/article/details/108887633
https://blog.csdn.net/cuizhiyi2008/article/details/102784754

const与形参

见上面的引用传递

// 为了不修改源数据,又不消耗额外的内存
void func(const MyClass &item)

const修饰函数(返回值)

修饰的是函数的返回值
返回值的内容不能被修改,只能赋值给同类型的const的内容
const 只修饰指针类型的返回值,值传递方式的返回值没有任何意义

const dataType func();
const var=func(); // 这种是对的// 下面是错的
// const var;
// var=func()

const 成员函数

在成员函数声明和定义的后面加入关键字const,表示const成员函数可以使用类中的所有成员变量,但是不能修改他们的值
见’c+±面向对象’

内联函数 – 还没看


http://www.ppmy.cn/news/3484.html

相关文章

LinkedList与链表

目录 1. 链表的概念&#xff1a; 2.链表的实现 ArrayList和LinkedList的对比&#xff1a; 链表是一种物理存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 根据前一章顺序表的介绍&#xff0c;我们发现对于顺序的删除和添加元素…

linux批量操作文件命令总结

总结下常用的linux命令&#xff0c;linux下的命令组合着实强大。有时候即便是使用的windows系统也可以在Dos窗口下使用linux下的一些命令工具&#xff0c;完成一些文本日常处理。 查找所有文件 find ./ -name "*.log" 查找某一后缀的文件并删除 find ./ -name &qu…

C# !(null包容)运算符的使用

总目录 文章目录总目录前言一、!(null包容&#xff09;运算符是什么&#xff1f;二、!(null包容&#xff09;运算符如何使用&#xff1f;1.使用2.扩展-预处理器指令启用或关闭null检查总结前言 本文主要讲解&#xff01;&#xff08;null包容&#xff09;运算符的使用&#xf…

内核动力之源——内存管理

目录 内存管理背后的故事 内存管理概述 常见内存分配策略 LwIP的宏配置及内存管理 见招拆招——动态内存堆 数据结构描述 函数实现 ​以不变应万变——动态内存池 数据结构描述 函数实现 使用C库管理内存策略 无论在哪种系统中&#xff0c;动态内存都是一个非常重要的…

【内网安全-基础】基础知识、信息收集、工具

目录 一、基础知识 1、内网&#xff1a; 2、工作组&#xff1a; 3、域(Domain)&#xff1a; 二、基础信息收集 1、判断是否在域内 2、机器角色判断 3、出网协议判断 4、端口判断 三、常规信息收集 1、常用命令 2、常用命令 3、工具&插件 LadonGO CS插件 Adfi…

基于PHP和MySQL的新闻发布系统

关于世界杯⚽️ 国际足联世界杯&#xff08;FIFA World Cup&#xff09;&#xff0c;简称“世界杯”&#xff0c;是由全世界国家级别球队参与&#xff0c;象征足球界最高荣誉&#xff0c;并具有最大知名度和影响力的足球赛事。世界杯全球电视转播观众超过35亿 。世界杯每四年举…

传输层协议 —— TCP(图解2)

​ 目录 一、前言 二、重传机制 1. 超时重传 2. 快速重传 3. SACK 4. D-SACK 三、滑动窗口 1. 发送方的滑动窗口 2. 程序是如何表示发送方的四个部分 3. 接收方的滑动窗口 四、流量控制 五、拥塞控制 1. 慢启动 2. 拥塞避免 3. 拥塞发生 4. 快速恢复 六、TCP…

内卷起来,2023年外贸B2B企业怎么通过独立站吸引客户的注意

从国外疫情解封后&#xff0c;中国在2022年的最后一个月也解封了&#xff0c;我们努力了三年&#xff0c;现在不再查核酸、健康码&#xff0c;多家航空公司重新开通了国际航班。对许多外贸公司来说&#xff0c;是“外贸春天”的到来。那么即将到来的2023年&#xff0c;外贸B2B企…