*&vs & 将变量传递给函数

*& vs & in passing variable to function

本文关键字:函数 变量 vs      更新时间:2023-10-16

我试图理解C++中的引用和指针,但我偶然发现了这个

#include<iostream> 
using namespace std; 
void swap(char * &str1, char * &str2) 
{ 
char *temp = str1; 
str1 = str2; 
str2 = temp; 
} 
int main() 
{ 
const char *str1 = "GEEKS"; 
const char *str2 = "FOR GEEKS"; 
swap(str1, str2); 
cout<<"str1 is "<<str1<<endl; 
cout<<"str2 is "<<str2<<endl; 
return 0; 
} 

函数 Swap 中的*&是什么,并与我学到的&(按引用传递(进行比较,性能是否有任何不同,或者它们是如何工作的,我应该使用什么?

void swap(char &str1, char &str2) 
{ 
char temp = str1; 
str1 = str2; 
str2 = temp; 
} 

可以在声明中引用任何类型。

例如

#include <iostream>
int main()
{
const char *s = "Hello";
const char * &reference_to_s = s;
std::cout << reference_to_s << 'n';
}

同一程序也可以通过以下方式重写

#include <iostream>
using T = const char *;
int main()
{
T s = "Hello";
T & reference_to_s = s;
std::cout << reference_to_s << 'n';
}

因此,函数的参数swap

void swap(char * &str1, char * &str2); 

是对指向非常量字符串/数组的指针的引用。

在第一次调用中,尝试交换通过引用传递的两个指针的值。

然而这个电话

swap(str1, str2); 

不正确,因为参数的类型为const char *,而声明的参数没有限定符const

使用上面显示的别名声明,您的程序可以像

#include <iostream>
using T = const char *;
void swap( T &s1, T &s2 )
{
T temp = s1;
s1 = s2;
s2 = temp;
}
int main()
{
T str1 = "GEEKS"; 
T str2 = "FOR GEEKS"; 
std::cout << "str1 is " << str1 << 'n'; 
std::cout << "str2 is " << str2 << 'n';
std::cout << 'n';
swap( str1, str2 ); 
std::cout << "str1 is " << str1 << 'n'; 
std::cout << "str2 is " << str2 << 'n'; 
std::cout << 'n';
}

它的输出是

str1 is GEEKS
str2 is FOR GEEKS
str1 is FOR GEEKS
str2 is GEEKS

使引用更清晰的下一步是将别名声明和非模板函数swap替换为模板函数swap

#include <iostream>
template <typename T>
void swap( T &s1, T &s2 )
{
T temp = s1;
s1 = s2;
s2 = temp;
}
int main()
{
const char *str1 = "GEEKS"; 
const char *str2 = "FOR GEEKS"; 
std::cout << "str1 is " << str1 << 'n'; 
std::cout << "str2 is " << str2 << 'n';
std::cout << 'n';
swap( str1, str2 ); 
std::cout << "str1 is " << str1 << 'n'; 
std::cout << "str2 is " << str2 << 'n'; 
std::cout << 'n';
char c1 = 'A';
char c2 = 'Z';
std::cout << "c1 is " << c1 << 'n'; 
std::cout << "x2 is " << c2 << 'n'; 
std::cout << 'n';
swap( c1, c2 );
std::cout << "c1 is " << c1 << 'n'; 
std::cout << "x2 is " << c2 << 'n'; 
std::cout << 'n';
}

程序输出为

str1 is GEEKS
str2 is FOR GEEKS
str1 is FOR GEEKS
str2 is GEEKS
c1 is A
x2 is Z
c1 is Z
x2 is A

因此,在swap的第一个调用中,引用的类型是const char *。在swap的第二次调用中,引用的类型为char

它是对指针的引用。这样,函数不仅可以访问指针指向的内容,还可以修改传入的指针本身(它可以更改传入指针指向的内容,因此它指向其他内容(。

如果将对整数的引用传递给交换函数,则将一个变量的数据复制到另一个变量,如下所示:

void swap(int &a, int &b) 
{ 
int temp = a; 
a = b; 
b = temp;
} 
int main() 
{ 
int a = 1; 
int b = 5; 
std::cout<<"a's adress before swap: "<< &a <<'n'; 
std::cout<<"b's adress before swap: "<< &b <<'n'; 
swap(a, b); 
std::cout<<"a's adress after swap: "<< &a <<'n'; 
std::cout<<"b's adress after swap: "<< &b <<'n'; 
return 0; 
} 

输出为:

a's adress before swap: 0x7ffeeccaba68
b's adress before swap: 0x7ffeeccaba64
a's adress after swap: 0x7ffeeccaba68
b's adress after swap: 0x7ffeeccaba64

所以它a’s数据复制到temp,然后将b’s数据复制到a,最后temp’s数据复制到b。如果您传递像整数这样的小对象是可以的,但是如果你传递像类对象这样的大对象来交换函数,可能会花费大量的时间和空间。

另一方面,如果您将指向指针的引用传递给交换函数,则只会跟踪指针指向的位置。例如:

#include <iostream>
void swap(int *&a, int *&b){
int *temp = a;
a = b;
b = temp;
}
int main(){
int x = 1;
int y = 5;
int *a = &x;
int *b = &y;
std::cout << "where a points before swap: " << a << 'n';
std::cout << "where b points before swap: "<< b << 'n';
swap(a, b);
std::cout << "where a points after swap: " << a << 'n';
std::cout << "where b points after swap: "<< b << 'n';
return 0;
}

请注意,在输出中,其中ab点在swap后追逐:

where a points before swap: 0x7ffee1738a68
where b points before swap: 0x7ffee1738a64
where a points after swap: 0x7ffee1738a64
where b points after swap: 0x7ffee1738a68

在交换函数中,首先tempa(指向x(点,然后ab(指向y(点,最后btemp点(指向x(。因此,它只是交换了指针指向的位置,并没有复制任何重要数据。因此,如果需要交换大数据对象,则引用指针对于时间和空间是更好的。

传递对指针的引用与将引用传递给任何其他类型的变量非常相似。因此,在函数中:

void swap(char * &str1, char * &str2) {
\..

两个参数的类型char*(指针到字符或 C 样式字符串(。

实际上,引用实际上是每个参数的地址,因此,当函数"交换"指针时,交换在调用代码中也是有效的。

如果参数只是简单地char*(而不是char* &(,那么传递的"指针"将是调用代码中它们值的副本,并且在函数中对它们所做的任何操作都不会在该调用代码中产生影响。(但请注意:该函数仍然可以更改参数指向的数据- 它只是无法根据需要更改/修改实际指针!

但是,在您的"建议的替代方案"中,您有:

void swap(char &str1, char &str2) {
//..

您正在更改参数的实际类型!在这里,您将引用传递给单个字符(char变量(的引用(即地址(,而不是字符串的(起始地址(。