Use of the & operator in C++ function signatures
我目前正在阅读加速C++,我意识到我并不真正理解如何在函数签名中工作。
1 | int* ptr=# |
意味着ptr现在将地址保存到num,但这意味着什么?
1 | void DoSomething(string& str) |
据我所知,这是一个变量的传递引用(这意味着传递地址),但当我这样做时
1 2 3 4 | void DoSomething(string& str) { string copy=str; } |
它创建的是str的一个副本。我认为它会引发一个错误,因为我正试图将指针赋给一个变量。
这里发生了什么?在函数调用中使用*和&;意味着什么?
引用不是指针,尽管它们有相似的用途,但它们是不同的。您可以将引用视为另一个变量的别名,即具有相同地址的第二个变量。它不包含地址本身,只引用与初始化变量相同的内存部分。
所以
1 2 3 4 5 6 7 8 9 10 | string s ="Hello, wordl"; string* p = &s; // Here you get an address of s string& r = s; // Here, r is a reference to s s ="Hello, world"; // corrected assert( s == *p ); // this should be familiar to you, dereferencing a pointer assert( s == r ); // this will always be true, they are twins, or the same thing rather string copy1 = *p; // this is to make a copy using a pointer string copy = r; // this is what you saw, hope now you understand it better. |
C++中的EDCOX1×0字符是双重用途的。这可能意味着(至少)
您在函数签名中引用的用法是2的一个实例。参数
1 2 3 4 | void Example() { string s1 ="example"; string& s2 = s1; // s2 is now a reference to s1 } |
我建议在引用中签出C++ FAQ条目,因为这是对它们的一个很好的介绍。
- https://isocpp.org/wiki/faq/references网站
在加速C++的第10章之前,你不应该知道指针。
引用为其他地方存在的某个对象创建另一个名称(别名)。就是这样。没有隐藏的指针或地址。别看窗帘后面!
想想一个叫罗伯特的人
1 | guy Robert; |
有时你可能想叫他鲍勃
1 | guy& Bob = Robert; |
现在鲍勃和罗伯特都指同一个人。你不知道他的地址(或电话号码),只是同一件事的另一个名字。
在你的职能范围内
1 2 3 4 | void DoSomething(string& str) { string copy=str; } |
它的工作原理完全相同,
不要为这是如何发生的而烦恼,只需将引用视为某个对象的名称即可。编译器必须弄清楚如何连接这些名称,而不必这样做。
在分配变量的情况下(例如,
在函数参数中,使用和号意味着要将访问或引用传递给变量内存中的同一物理区域(如果不使用,则发送一个副本)。如果使用星号作为参数的一部分,则指定传递的是一个变量指针,这将实现几乎相同的效果。这里的区别在于,如果使用了一个和号,则可以通过名称直接访问变量,但是如果传递一个指针,则必须遵从该指针以获取和操作实际值:
1 2 3 4 5 6 7 8 9 10 11 | void increase1(int &value) { value++; } void increase2(int *value) { (*value)++; } void increase3(int value) { value++; } |
请注意,
1 2 3 4 5 6 7 | int main() { int number = 5; increase1(number); increase2(&number); increase3(number); return 0; } |
3个函数调用结束时,
它是一个允许函数修改传递的字符串的引用,不像普通的字符串参数那样,修改不会影响传递给函数的字符串。
您经常会看到一个const string类型的参数,这是为了提高性能而进行的,因为内部引用不会创建字符串的副本。
1 | int* ptr=# |
第一种情况:因为ptr是内存,它存储变量的地址。运算符返回内存中num的地址。
1 | void DoSomething(string& str) |
第二种情况:与号运算符用于表示变量正在通过引用传递,并且可以由函数更改。
因此,基本上,&operator根据上下文有两个函数。
在以下情况下:
1 | int* ptr=# |
您要声明一个名为
在以下情况下:
1 | void DoSomething(string& str) |
您要将dosomething()方法的第一个参数声明为"对字符串的引用"类型。实际上,这是C++定义"按需传递"的方式。
请注意,虽然
虽然pass-by引用可以由编译器通过将地址作为指针传递来实现,但在语义上它与地址或指针没有任何关系。简单来说,它只是变量的别名。
C++有很多语法不同的上下文中使用不同语义的情况,这就是这些情况之一。
你无法从
另一种考虑引用(尽管有点不正确)的方法是对未引用的指针使用句法糖分。