IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++ primer 学习笔记 第六章 -> 正文阅读

[C++知识库]c++ primer 学习笔记 第六章

第六章

函数基础

  • 函数执行的第一步是隐式的定义并初始化他的形参。
  • 如果局部静态变量没有显式的初始值,他将执行值初始化,内置类型的局部静态变量初始化为零。
  • 在头文件中进行函数声明,含有函数声明的头文件应该被包含到定义函数的源文件中。
  • 使用引用避免拷贝,效率高,而且某些类类型不支持拷贝操作。如果函数无需修改引用形参的值,声明为常量引用。

温习----指针引用与const

int i = 42;
const int *cp = &i;	 //正确:但是cp不能改变i
const int &r = i; 	// 正确:但是r不能改变i 
const int &r2 = 42; 	//正确, 常量引用可以引用常量
int *p = cp;	//错误: p的类型和cp的类型不匹配
int &r3 = r;	//错误: r3的类型和r的类型不匹配
int &r4 = 42;	//错误:不能用字面值初始化一-个非常量引用

尽量使用常量引用。

数组形参

  • 为函数传递一个数组时,实际上传递的是指向数组元素的指针。

  • 当函数不需要对数组元素执行写操作的时候,数组形参应该是指向const的指针。只有当函数确买要改变元素值的时候,才把形参定义成指向非常量的指针。

温习

  • int *matrix[10]; //10个指针构成的数组
    int (*matrix)[10]; //指向含有10个整数的数组的指针
    
  • 返回局部对象的引用是错误的。同样,返回指向局部对象的指针也是错误的。一旦函数完成,局部对象被释放,指钍将指向一个不存在的对象。

函数返回值

数组不能拷贝,所以函数不能返回数组。

声明一个返回数组指针的函数

//Type ( *function (parameter_ list) ) [dimension]
int (*func(int i))[10];	//函数返回指向int数组的指针
  • func(int i) 表示调用func函数时需要一个int类型的实参。
  • (*func(inti)) 意味着我们可以对函数调用的结果执行解引用操作。
  • (*func(int i)) [10]表示解引用func的调用将得到一个大小是10的数组。
  • int (*func(int i)) [10]表示数组中的元素是int类型。

使用尾置返回类型

// func 接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
auto func(int i) -> int(*) [10] ;

函数重载

  • 不允许两个函数除了返回类型外其他所有的要素都相同。

  • 一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来

Record lookup (Phone);
Record lookup (const Phone);//重复声明了Record lookup (Phone)

Record lookup (Phone*);
Record lookup (Phone* const);//重复声明了Record lookup (Phone*)
  • 如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载
//对于接受引用或指针的函数来说,对象是常量还是非常量对应的形参不同
//定义了4个独立的重载函数
Record lookup (Account&);	// 函数作用于Account 的引用
Record lookup (const Account&);	// 新函数,作用于常量引用
Record lookup (Account*);	//新函数,作用于指向Account的指针
Record lookup (const Account*);	//新函数,作用于指向常量的指针
  • const_cast:在下面这个版本的函数中,首先将它的实参强制转换成对const 的引用,然后调用了shorterString函数的const版本。const版本返回对const string 的引用,这个引用事实上绑定在了某个初始的非常量实参上。因此,我们可以再将其转换回一个普通的string&, 这显然是安全的。
string &shorterString(string &s1, string &s2){
	auto &r = shorterString(const_cast<const string&>(s1),
                             const_cast<const string&> (s2) );
	return const_cast<string&>(r);
}//发问:这样的意义是不重写一遍代码?

默认实参

  • 一旦某个形参被赋予了默认值,则其后面的所有形参都必须有默认值。
  • 只能省略尾部的默认实参,从右到左看。
  • 默认实参可以多次声明,但不能修改一个已经存在的默认值。
string screen(SZ, SZ, char ='');
string screen(SZ, SZ, char = '*');  //错误:重复声明
string screen(sz = 24, sz = 80, char);    //正确:添加默认实参          

内联函数和constexpr函数

inline : 内联函数可避免函数调用的额外开销,但是只是像编译器发出的一个请求,编译器可以选择忽略它。

constexpr函数(constexpr function): 指能用于常量表达式的函数。

  • 约定:函数的返回类型及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句。

  • 为了能在编译过程中随时展开,constexpr函数被隐式地指定为内联函数。

  • 允许constexpr函数的返回值并非一个常量。

    • //如果arg是常量表达式,则scale(arg)也是常量表达式.
      constexpr size_t scale (size_t cnt) { return new_sz() * cnt; }
      //当scale的实参是常量表达式时,它的返回值也是常量表达式,反之则不然:
      int arr[scale(2)];	//正确: scale(2)是常量表达式
      int i = 2; 			// i不是常量表达式
      int arr[scale(i)];	//错误: scale(i)不是常量表达式
      

函数匹配

  • 函数每个实参的匹配都不劣于其他可行函数需要的匹配。

  • 至少有一个实参的匹配优于其他可行函数提供的匹配。

如果在检查了所有实参之后没有任何一个函数脱颖而出,则该调用是错误的。编译器将报告二义性调用的信息。

调用重载函数时应尽量避免强制类型转换。如果在实际应用中确实需要强制类型转换,则说明我们设计的形参集合不合理。

函数指针

声明函数指针

要想声明一个可以指向该函数的指针,只需要用指针替换函数名即可。

// pf指向一个函数, 该函数的参数是两个const string 的引用,返回值是bool类型
bool (*pf)(const string &, const string &); //未初始化

使用函数指针

函数名作为值使用时,该函数自动转换为指针。

pf = func;		//pf指向名为func的函数
pf = &func;		//等价的赋值语句:取地址符是可选的

直接使用指向函数的指针调用该函数,无须提前解引用指针,但指向不同函数类型的指针间不存在转换规则。

bool b1 = pf("hel1o", "goodbye");	//调用func函数
bool b2 = (*pf)("hello", "goodbye");	//一个等价的调用
bool b3 = func("hello","goodbye"); 	// 另一个等价的调用

重载函数的指针

void ff(int*);
void ff(unsigned int);
void (*pf1)(unsigned int) = ff; 	// pf1指向ff (unsigned)
//编译器通过指针类型决定选用哪个函数,指针类型必须与重载函数中的某一个精确匹配
void (*pf2)(int) = ff;		//错误:没有任何一个ff与该形参列表匹配
double (*pf3)(int*) = ff;	//错误: ff和pf3的返回类型不匹配
typedef decltype(lengthCompare) *FuncP2; //指向函数的指针

decltype的结果是函数类型,所以只有在结果前面加上*才能得到指针。

返回指向函数的指针

  • 使用类型别名,最简单。

    using F = int (int*, int);		// F是函数类型,不是指针
    using PF = int (*)(int*, int);	// PF是指针类型
    
    PF f1 (int);	//正确:PF是指向函数的指针,f1返回指向函数的指针
    F f1 (int);		//错误: E是函数类型f1不能返回一个函数
    F *f1 (int);	//正确:显式地指定返回类型是指向函数的指针
    
    
  • 尾置返回

    int (*f1(int))(int*, int);
    auto f1(int) -> int (*)(int*, int); //尾置返回
    

由内而外解析:首先f1带有形参列表, 是一个函数,(类比)直接调用一个函数就是使用其返回值,前面加了’*’,说明返回的是一个指针。进一步观察,返回的指针也带有参数列表,所以这个指针指向的是一个函数,且函数的返回类型是int。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:41:17  更:2021-08-27 11:42:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:54:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码