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——第六章

  • 6.1

形参:函数定义的时的参数—也就是无赋值的变量(作用是说明参数的类型)

实参:调用函数时使用的参数—也就是有赋值的变量(函数实际操作的对象)

  • 6.2

知识点1:函数包括返回类型、函数名字、形参列表和函数体,函数调用完成两项工作:①实参初始化对应形参 ②将控制权转移给被调用函数 ,通过调用用运算符{}来执行函数

知识点2:定义不带形参的函数两种方法:①书写空的形参列表 ②定义函数类型为void

知识点3:任意两个形参不可同名,且函数最外层作用域中的局部变量不可使用与函数形参一样的名字

(a)函数返回类型与定义类型不匹配

(b)未标明函数返回类型

(c)形参名字重复

(d)无调用运算符{}

  • 6.3 & 6.4

求阶乘的函数在测试的时候要注意不要超过了int范围,例如输入55得到的结果就会等于0

#include <cmath>
#include<iostream>
#include<string>

int fact(int i)
{
	int ret = 1;
	while (1 < i)
	{
		ret *= i;
		i--;
	}
	return ret;
}
int main()
{
	int j,k;
	std::cin >> j;
	k = fact(j);
	std::cout << k << std::endl;
}
  • 6.5

编写时注意函数名字不能写为abs,因为std空间中定义了abs函数,由于形参数量和形参类型都可以与std所定义的相同或者可以相互转换,因此不会实现重载确定(函数匹配),从而报错。

#include <cmath>
#include<iostream>
#include<string>

double my_abs(double i)
{
	if (i > 0)
		return i;
	else if (i < 0)
		return -i;
	else
		return 0;
}
int main()
{
	double j,k;
	std::cin >> j;
	k = my_abs(j);
	std::cout << k << std::endl;
}
  • 6.6 & 6.7

知识点1:形参和函数体内定义的变量统称为局部变量,这种只存在于块执行期间的对象称为自动对象

知识点2:局部静态对象是直到程序结束时才被销毁的对象,不受块的约束。局部静态对象在重复执行时只会被赋值一次。

#include <cmath>
#include<iostream>
#include<string>

double my_abs()
{
	static int a = 0;
	return a++;
}
int main()
{
	for (int i = 0; i != 10; i++)
		std::cout << my_abs() << std::endl;
}
  • 6.8

知识点1:函数只可以定义一次,但可以声明多次,如果一个函数永远也不会被我们用到,那么它可以只有声明没有定义,函数声明也叫作函数原型。

知识点2:建议函数在头文件(.h)中声明,在源文件中(.c)定义。定义函数的源文件应该把含有函数声明的头文件包含起来,编译器负责验证函数的定义与声明是否匹配。

知识点3:记住声明是一条语句,因此末尾要加句号!

#include <cmath>
#include<iostream>
#include<string>
int fact(int i);
double my_abs();
  • 6.9

知识点1:C++语言支持分离式编译,这允许我们把程序分割到几个文件中去,每个文件独立编译,生成相应的 .obj(windows)或 .o(UNIX)的文件,然后再将对象文件链接起来生成可执行文件。

这里可将函数的定义放在fact.cc文件,而函数的声明在factMain.cc文件中

  • 6.10

知识点1:值传递只会影响形参,不会影响实参,因此实参传值给形参的过程实际上是一个拷贝过程。若传递的是一个指针,则相当于实参形参是两个指向同一对象的不同指针。

知识点3:C++语言中建议使用引用类型的形参代替指针。(当对象很大时,拷贝往往比较低效,使用引用会更好)

#include <cmath>
#include<iostream>
#include<string>

double exchange(double &a,double &b)
{
	b = a + b;
	a = b - a;
	b = b - a;
	return 0;
}
int main()
{
	double a, b;
	std::cin >> a >> b;
	std::cout << "交换前两个数为: " << a << " " << b << std::endl;
	exchange(a, b);
	std::cout << "交换后两个数为: " << a << " " << b << std::endl;
}
  • 6.11

知识点1:引用传递会修改实参的值,当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象,如果函数无须改变引用形参的值,最好将其声明为常量引用。

知识点2:如果要让函数同时返回多个值,有两种办法:
①定义一个新的数据类型,让它可以包含多个值的信息、
②给函数传入一个额外的引用实参,令其保存字符出现的次数

#include <cmath>
#include<iostream>
#include<string>

//寻找字符串中某个字符出现的次数及第一次出现的位置
int find_char(const std::string &a , char c ,int &occurs)
{
	int position = a.size();
	for (int i = 0; i < position; i++)
	{
		if (a[i] == c)
		{
			if (position == a.size())
				position = i;
			occurs++;
		}
	}
	return position;
}
int main()
{
	std::cout << "输入字符串:" << std::endl;
	std::string s;
	std::cin >> s;
	std::cout << "输入字符:" << std::endl;
	char a;
	std::cin >> a;
	int val = 0;
	int num = find_char(s, a, val);
	//由于num是从0开始计算的,因此结果要加1
	std::cout << "字母第一次出现的位置为" << num+1 << std::endl;
	std::cout << "字母出现的次数为" << val << std::endl;
}
  • 6.12

第10题已经用了传址的方式进行交换,不过C++倡导使用引用传递的方式以区别值传递

  • 6.13

void f(T) :值传递,不可改变形参

void f(&T):引用传递,可以改变形参

  • 6.14

如下情况将形参定义为引用:

1.通过形参调用修改函数的值,如swap函数
2.通过一次调用获得多个结果值
3.传递大型对象时,避免复制形参

如下情况不可将形参定义为引用:

1.不需要通过函数调用修改实参的值,如求绝对值的函数
2.当使用非常量引用,而实参是字面值、表达式、需要转换的不同类型的对象时

void swap(int &a,int &b);
int a=2;
double b=3.0;
//以下三个表达式均会报错,非常量引用的初始值必须为左值
f(a,5);
f(a+2,a);
f(a,b);
  • 6.15

先将题目代码贴上来

std::string::size_type find_char(const std::string &s,char c,std::string::size_type &occurs)
{
	auto ret = s.size();
	occurs = 0;
	for (decltype(ret) i = 0; i != s.size(); ++i)
	{
		if (s[i] == c)
		{
			if (ret == s.size())
				ret = i;
			occurs++;
		}
	}
	return ret;
}

s是常量引用,因为s是不可以进行修改的

c可能是一个临时变量,因此无需使用引用类型,并且也没必要修改它本身

occurs是普通引用,如果设置为常量引用,则无法计算出现次数

  • 6.16

局限性:这个函数不能传递const string参数

这里输入的string对象是不可修改的,所以应该设置为常量引用的类型:

bool is_empty(const std::string &s)
{
    return s.empty();
}
  • 6.17

形参不同,改写的形参设置为普通引用,而寻找的形参设置为常量引用

//寻找字符串中的大写字母
bool is_capitalize(const std::string s)
{
	for (int i = 0; i < s.size(); i++)
		if (s[i] >= 'A' && s[i] <= 'Z')
			return true;
	return false;
}

//将字符串中的大写字母改为小写字母
std::string to_capitalize(std::string s)
{
	for (int i = 0; i < s.size(); i++)
		if (s[i] >= 'A' && s[i] <= 'Z')
			s[i] += 32;
	return s;
}
  • 6.18

(a)比较两个矩阵是否相等

bool compare(matrix &a,matrix &b);

(b) 改变一个迭代器中的某个值

std::vector<int>::iterator change_val(int a, std::vector<int>::iterator b);
  • 6.19

(a)非法

形参与实参数量不齐

(b)合法

形参名是可选的,但由于我们无法使用未命名的形参,所以形参一般都应该有个名字。但有时函数的部分形参不会被用到,那么就对这类形参不命名以表示在函数体内不会使用它。

(c)合法

传入的实参只要能转换为形参的格式就为合法的

(d)合法

  • 6.20

知识点1:实参初始化形参时会忽略掉顶层const,因此对顶层const的形参,传给它常量或非常量对象都是可以的

知识点2:可以用非常量引用初始化一个常量对象,但不可以用常量引用初始化非常量对象。

因此对于int & / int *类型的形参,只能用 int 类型对象初始化,而不能用字面值,求值结果为int的表达式,需要转换的对象或者const int类型的对象。

知识点3:C++允许用字面值初始化常量引用

知识点4:把函数不会改变的形参定义成普通引用是一种常见错误,这样做不仅会极大的限制函数所能接受的实参类型,而且还会造成意想不到的错误,例如在使用常量引用的函数中就无法调用使用非常量引用的函数。

  • 6.21
int return_max(int a,int* b)
{
	if (a > *b)
		return a;
	else
		return *b;
}
  • 6.22
void swap(int* a,int* b)
{
	int* tmp;
	tmp = a;
	a = b;
	b = tmp;
}
  • 6.23

知识点1:数组的两个性质:
①不允许拷贝数组,所以不可以使用传值的方式使用数组参数(传值即为拷贝)
②通常数组的传递使用的是指针形式,传递的是指针的首地址。

尽管不能值传递,但可以把形参写成类似数组的形式:

void print(const int*);
void print(const int[]);
void print(const int[10]); //维度表示我们期望数组含多少元素,实际上不一定

注意:以数组作为形参的函数必须确保使用数组时不会越界

知识点2:以数组作为形参时,函数并不知道数组的确切大小,有3种技术来为此提供额外信息

①使用标记指定数组长度
该方法适合C风格字符串,因为C风格字符串后面跟着一个空字符,函数在处理空字符串时遇到空字符停止。

void print(const char *p)
{
	if (p)                       //p不是空指针
		while (*p)               //p不是指向空字符
			std::cout << *p++;
}

②使用标准库规范
传递指向数组数组首元素和尾后元素的指针,这种方法受到了标准库技术的启发。

void print(const int *beg,const int *end)
{
	while (beg != end)
		std::cout << *beg++ << std::endl;
}

begin指向要输出的首元素,end指向尾元素的下一位

int j[2] = {0,1};
print(begin(j),end(j));

③显式传递一个表示数组大小的形参

void print(const int a[],size_t size)
{
	for (size_t i = 0; i != size; i++)
		std::cout << a[i] << std::endl;
}

只要传入的size值没超过数组实际大小,函数就是安全的

int j[] = {0,1};
print(j,end(j) - begin(j));
  • 6.24

知识点1:
引用的数组:不合法,不存在一个数组,里面存放的都是引用

f(int &a[4])               //错误

数组的引用:合法的,相当于对数组名起一个别名

f(int (&a)[4])             //正确,a是对有4个整数的整形数组的引用

知识点2:
数组的指针:合法,其实为一个指向数组首元素的指针

int (*matrix)[10];

指针的数组:合法,由指针构成的数组

int *matrix[10];

24题中形参传入的是一个数组的指针,代码没有问题。但是会让人误认为是传入10个元素,然而实际上不一定是10个,而且程序还不会因此而报错。虽然传入的 ia 是指针,但是在输出时却可以直接使用下标运算。

void print(const int a[],size_t size)
{
	for (size_t i = 0; i != size; i++)
		std::cout << a[i] << std::endl;
}

int main()
{
	int a[3] = { 1,2,3 };
	print(a, 3);
}
  • 6.25

知识点1:main函数的参数是从操作系统命令行得到的,在命令行中输入可执行文件名以及对应参数,可将命令行实参传递到main的形参中去

知识点2:命令行参数中第一个参数argc是参数个数,第二个参数argv是一个指向数组的指针,该数组是一个指针数组

在这里插入代码片
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 13:50:50  更:2021-08-14 13:52:43 
 
开发: 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 13:46:32-

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