void swap(double& val1,double& val2); 这是什么意思

void swap(double& val1,double& val2);这是什么意思?

定义了一个叫做 swap 的函数,它接受两个双精度数的引用作为参数
在 C++ 中,& 符号用于表示引用。通过传递引用作为参数,函数可以直接修改传递给它的参数的值,而不是创建参数的副本。
通过传递引用而不是传递参数的副本,可以避免不必要的内存开销,并且可以确保原始变量的值被正确交换。

****传递引用传递参数的副本是什么意思?

在函数调用中,参数可以通过值传递引用传递来传递给函数。

传递参数的副本(值传递):
当你通过值传递参数时,函数会创建参数的副本,并在函数内部使用这些副本来执行操作。原始参数的值在函数内部是不受影响的。
这意味着如果在函数内部修改了参数的值,只会影响到参数的副本,而不会影响原始参数的值

传递引用:
通过引用传递参数时,函数接受参数的引用而不是参数的副本。这意味着函数可以直接访问并修改原始参数的值。
通过引用传递参数可以节省内存,因为不需要创建参数的副本。同时,也可以确保对参数的修改会影响到原始参数。
在 C++ 中,通过在函数参数前加上 & 符号来声明引用参数。当你传递一个变量给引用参数时,你实际上传递的是该变量的地址,而不是它的值的副本。这使得函数可以直接访问并修改该变量的值。

为什么这个函数的目的通常是交换两个双精度数的值呢?
这个函数的目的通常是交换两个双精度数的值,因为交换两个值是一个常见的编程任务,特别是在排序算法和其他算法中经常需要这样的操作。在实际编程中,交换两个变量的值是一种常见的操作,可以用于许多不同的情况。

使用函数来进行交换的好处在于可以将这个操作封装成一个独立的功能单元,使得代码更易读、更易维护。而将参数声明为引用可以确保交换操作对原始变量产生影响,而不是仅仅在函数内部交换参数的副本。

因此,编写一个交换两个双精度数值的函数是很常见的,而这个函数的参数使用引用是为了确保交换操作对原始值产生影响,而不是仅仅在函数内部交换参数的副本。

有没有什么实际的应用例子?
在实际应用中,交换两个值的操作可能在许多情况下都会被用到。以下是一些示例:

排序算法:在许多排序算法中,如冒泡排序、快速排序等,经常需要交换数组或容器中元素的位置来实现排序。

图形处理:在图形处理中,可能需要交换两个点的坐标值来实现镜像、旋转等变换操作。

内存管理:在某些情况下,需要在内存中交换数据块或缓冲区的内容,以实现数据的重新排序或优化存储结构。

并行计算:在并行计算中,可能需要交换不同线程或进程之间的数据值,以实现数据的同步或协调操作。

加密算法:在加密和解密算法中,可能需要交换密钥或数据块的值来实现不同阶段的计算操作。

这些只是一些常见的示例,实际上,交换两个值的操作可以在各种领域和场景中被广泛应用。因此,编写一个交换两个值的函数是很有用的,可以在各种情况下重复使用

点击查看代码
void swap(double& val1,double& val2);
//std:swap() 对double类型的极简版?
/*这是函数原型,它声明了一个名为 swap 的函数,
接受两个 double 类型的引用作为参数,并且不返回任何值。
这个原型告诉编译器在后面的代码中会有一个名为 swap 的函数,
以便在 main 函数中调用它。*/

int main()
{
    double num1{}, num2{};
    std::cout<<"please enter 2 numbers:"<<'\n';
    std::cin>>num1>>num2;
    if(num1>num2)//swap values around so that the smallest is in num1.
    swap (num1,num2);
std::cout << "the numbers in order are"
<<num1<<"and"<<num2<<'\n';
}
/*
这是程序的主函数。它首先声明了两个 double 类型的变量 num1 和 num2,
然后提示用户输入两个数字,并将输入的值分别存储在这两个变量中。
接着,它检查 num1 和 num2 的值,
如果 num1 的值大于 num2 的值,则调用 swap 函数来交换它们的值,
确保 num1 存储的是较小的数。最后,它输出排序后的数字。
*/
void swap( double&val1 ,double&val2)
{
    double temp{val1};
    val1=val2;
    val2=temp;
}
/*这是 swap 函数的定义。
它接受两个 double 类型的引用作为参数,
并且不返回任何值。在函数体内部,
它使用一个临时变量 temp 来交换 val1 和 val2 的值,
确保 val1 存储的是原来 val2 的值,
而 val2 存储的是原来 val1 的值*/

为什么swap函数的原型和定义要分开写呢?
在C++中,函数的原型(也称为函数声明)和定义可以分开写的主要原因是为了提高代码的可读性和可维护性,并且支持模块化编程。这种做法有以下几个优点:

可读性和可维护性:将函数原型与函数定义分开可以使代码更加清晰易读。当阅读代码时,可以先看到函数的原型,从而了解函数的接口,包括参数类型和返回类型。然后在需要时,可以查看函数的定义来了解函数的具体实现细节。这样做使得代码更易于理解和维护,尤其是对于大型项目来说。

模块化编程:将函数原型和定义分开可以促进模块化编程的实践。在大型项目中,通常会将不同的功能模块分别实现在不同的源文件中,每个源文件可以包含一组相关的函数。通过在头文件中包含函数的原型,其他源文件可以访问并调用这些函数,而无需关心函数的具体实现细节。这种模块化的设计有助于降低代码的耦合度,提高代码的可重用性和可维护性。

编译优化:分离函数原型和定义还可以提高编译器的优化效率。当编译器在编译源文件时遇到函数调用时,如果函数的原型已经在可见范围内,它就可以对函数进行类型检查和参数匹配,并生成相应的调用代码。而函数的定义则可以在链接阶段进行处理,这样编译器就不需要在编译阶段重复处理函数的定义,提高了编译速度和优化效率。

函数原型和定义是什么来着?
函数原型(或称函数声明)是指在使用函数之前对函数进行简单的声明,包括函数的名称、参数列表和返回类型,但不包括函数的具体实现细节。它的主要作用是告诉编译器在后续代码中会有一个函数,以便编译器可以对函数进行类型检查和参数匹配。函数原型通常写在函数调用之前或者放在头文件中,以便其他源文件可以访问。

函数定义是指对函数的具体实现进行描述,包括函数的名称、参数列表、函数体和返回值。函数定义提供了函数的具体行为和功能。在C++中,函数定义通常写在源文件中,可以单独编译成目标文件,然后在链接阶段与其他目标文件进行链接。

函数原型告诉编译器有一个函数的存在和接口,
而函数定义提供了函数的具体实现细节。

那刚刚的int main为什么没有原型?

在C++中,int main函数通常是程序的入口点,用于指定程序开始执行的位置。在C++中,main函数有两种常见的形式:

不带参数的main函数:在传统的C++标准中,main函数通常被定义为不带参数的形式,即int main()或int main(void)。在这种情况下,可以省略函数原型,因为编译器会默认假设main函数的原型为int main()。
cpp
int main() {
// 程序的主要逻辑
return 0;
}
带参数的main函数:在C++11标准中,引入了带参数的main函数形式,即int main(int argc, char *argv[])或int main(int argc, char **argv)。这种形式用于接收命令行参数。对于带参数的main函数,通常需要显式地提供函数原型,以指明main函数接受的参数类型和返回类型。
cpp
int main(int argc, char *argv[]) {
// 程序的主要逻辑
return 0;
}
在这两种情况下,main函数的原型是隐含的或者由编译器默认提供的,因此通常不需要显式地提供函数原型。

`

点击查看代码
int sum_arrary(std::span<const int>values)

/*定义了一个名为 sum_array 的函数,
它接受一个 std::span 类型的参数 values,该参数表示一个常量整型数组的范围。

std::span 是 C++20 中引入的一种容器,用于表示一个连续内存范围。
它提供了对数组或其他序列的非拥有(non-owning)引用,
**允许你在不拷贝元素的情况下操作这些元素。**

const int 表示 values 中的元素是常量整型,
即不能通过 values 修改数组中的元素值,
表示 values 是一个常量整型的范围。

接下来在函数体中添加具体的实现逻辑。
*/

`

这个span是不是就是刚刚说的传递引用?
是的,std::span 可以看作是对数组的非拥有引用,因此在函数中使用 std::span 类型的参数可以实现对数组的引用传递。

通过使用 std::span,函数可以在不拷贝数组的情况下访问数组元素,并且可以获取数组的长度和执行其他操作,这使得函数参数更加灵活和高效。在这个例子中,函数 sum_array 接受一个 std::span 类型的参数 values,表示一个常量整型数组的范围,因此函数可以读取数组中的元素值但不能修改它们。

使用引用传递参数通常比值传递参数更高效,尤其是当参数为大型数据结构(如数组)时,因为它避免了数据的拷贝。

int total {};
for(int value:values)
total+= value;
return total;
}
这些是什么意思?

这段代码是 sum_array 函数的具体实现,用于计算传入整型数组范围中所有元素的和。让我解释一下:

cpp
int total {}; // 定义一个名为 total 的整数变量并初始化为 0
这行代码声明并初始化了一个整型变量 total,用于存储数组中所有元素的总和。

cpp
for(int value : values) // 遍历 values 中的每一个元素,将其赋值给 value
total += value; // 将当前元素的值加到 total 中
这是一个范围-based for 循环,用于遍历 values 中的每一个元素。在每次迭代中,将当前元素的值加到 total 变量中。

cpp
return total; // 返回数组中所有元素的总和
最后,return 语句用于将计算得到的数组所有元素的总和作为函数的返回值返回。

综合起来,这段代码实现了对传入整型数组范围中所有元素的求和操作,并将结果返回。

也就是说values数组的每一个数都一起加起来吗

是的,你理解得对。这段代码通过循环遍历 values 数组中的每一个元素,并将它们的值累加到变量 total 中,最终返回 total,即 values 数组中所有元素的总和。

所以":"的意思就是,“:”前的变量是用来储存":"后面的的数组的每一个值的吗?

没错,你理解得非常准确。在这个范围-based for 循环中,冒号 : 的左侧是一个变量(在这里是 int value),用来存储数组中每个元素的值。冒号 : 的右侧是要遍历的范围(在这里是 values 数组),循环将会迭代这个范围中的每个元素,并将其依次赋值给左侧的变量。

因此,在循环的每一次迭代中,value 变量都会被赋值为 values 数组中的一个元素的值,然后你可以在循环体中使用 value 变量来操作这个元素的值。

std::array<int,MAX_SIZE>values2;
/*
std::array<int,MAX_SIZE> values2;
这一行定义了一个名为 values2 的数组 (array),
其元素类型为整型 (int),大小为 MAX_SIZE,
这里 MAX_SIZE 是之前定义的编译时常量,值为 10。
数组是一种固定大小的数据结构,
大小在编译时就已确定,并且不能动态改变。*/

posted @   helloworld_0810  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示