*&vs & 将变量传递给函数
*& vs & in passing variable to function
我试图理解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;
}
请注意,在输出中,其中a
和b
点在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
在交换函数中,首先temp
点a
(指向x
(点,然后a
点b
(指向y
(点,最后b
点temp
点(指向x
(。因此,它只是交换了指针指向的位置,并没有复制任何重要数据。因此,如果需要交换大数据对象,则引用指针对于时间和空间是更好的。
传递对指针的引用与将引用传递给任何其他类型的变量非常相似。因此,在函数中:
void swap(char * &str1, char * &str2) {
\..
两个参数的类型char*
(指针到字符或 C 样式字符串(。
实际上,引用实际上是每个参数的地址,因此,当函数"交换"指针时,交换在调用代码中也是有效的。
如果参数只是简单地char*
(而不是char* &
(,那么传递的"指针"将是调用代码中它们值的副本,并且在函数中对它们所做的任何操作都不会在该调用代码中产生影响。(但请注意:该函数仍然可以更改参数指向的数据- 它只是无法根据需要更改/修改实际指针!
但是,在您的"建议的替代方案"中,您有:
void swap(char &str1, char &str2) {
//..
您正在更改参数的实际类型!在这里,您将引用传递给单个字符(char
变量(的引用(即地址(,而不是字符串的(起始地址(。
- 未使用的C++未优化的静态成员函数/变量
- 内联函数/变量的外部链接
- 同一函数中的静态函数变量初始化顺序
- 将非静态成员函数C 的使用无效,而将成员功能作为函数变量
- 如何从doxygen输出中排除类的无证件成员函数/变量
- 如何在LUA C API中分配全局LUA函数变量
- 如何将函数变量传递给C lambda函数
- 通过另一个C++函数更改函数变量
- c++11 lambda 真的支持闭包吗?函数变量中存在语义冲突
- C++:静态成员不能在声明时定义,但静态函数变量可以?
- apache-frift是否支持函数变量作为参数
- 类函数/变量在使用之前必须声明
- 函数变量去哪里
- 无法使用函数变量?错误表达式必须具有类类型
- 如何在main中使用函数变量
- 每当尝试打印函数变量时,C++ cout 错误
- 是否存在查看成员函数/变量的整洁等效项
- 访问友元类之间的函数变量
- 函数到函数变量
- 一个定义规则是否强制创建一个静态函数变量