我目前正在阅读Accelerated C ++,我意识到我并不真正理解&适用于功能签名。
int* ptr=#
表示ptr现在将地址保存为num,但这意味着什么?
void DoSomething(string& str)
据我所知,这是一个变量的引用传递(这意味着传递地址)但是当我做的时候
void DoSomething(string& str)
{
string copy=str;
}
它创建的是str的副本。我认为它会做的是引发错误,因为我正在尝试为变量指定一个指针。
这里发生了什么?使用*和&的含义是什么?在函数调用中?
答案 0 :(得分:34)
引用不是指针,虽然它们用于类似目的,但它们是不同的。 您可以将引用视为另一个变量的别名,即具有相同地址的第二个变量。它本身不包含地址,它只是引用与它初始化的变量相同的内存部分。
所以
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.
答案 1 :(得分:25)
C ++中的&
字符是双重目的。它可能意味着(至少)
您在函数签名中引用的用法是#2的实例。参数string& str
是对string
实例的引用。这不仅限于函数签名,它也可以在方法体中出现。
void Example() {
string s1 = "example";
string& s2 = s1; // s2 is now a reference to s1
}
我建议查看参考文献中的C ++ FAQ条目,因为它是对它们的一个很好的介绍。
答案 2 :(得分:13)
在进入Accelerated C ++第10章之前,你不应该知道关于指针的任何!
引用为其他地方存在的内容创建另一个名称,别名。而已。没有隐藏的指针或地址。不要看幕后!
想想一个名叫罗伯特的人
guy Robert;
有时你可能想叫他鲍勃
guy& Bob = Robert;
现在Bob和Robert都指的是同一个人。你没有得到他的地址(或电话号码),只是同一件事的另一个名字。
在你的功能中
void DoSomething(string& str)
{
string copy=str;
}
它的工作原理完全相同,str
是存在于其他地方的某个字符串的另一个名称。
不要理会这种情况,只需将引用视为某个对象的名称。 编译器必须弄清楚如何连接名称,你没有。
答案 3 :(得分:11)
在分配变量的情况下(即int* ptr = &value
),使用&符号将返回变量的地址(在本例中为value
的地址)。
在函数参数中,使用&符号表示您将访问或引用传递给变量内存中的相同物理区域(如果不使用它,则会发送副本)。如果您使用星号作为参数的一部分,那么您将指定传递变量指针,这将实现几乎相同的事情。这里的区别在于,使用&符号,您可以通过名称直接访问变量,但是如果您传递指针,则必须 deference 指针才能获取并操纵实际值:
void increase1(int &value) {
value++;
}
void increase2(int *value) {
(*value)++;
}
void increase3(int value) {
value++;
}
请注意increase3
对您传递的原始值不执行任何操作,因为只发送了一个副本:
int main() {
int number = 5;
increase1(number);
increase2(&number);
increase3(number);
return 0;
}
3个函数调用结束时number
的值为7,而不是8。
答案 4 :(得分:4)
它是一个允许函数修改传递的字符串的引用,与普通的字符串参数不同,其中修改不会影响传递给函数的字符串。
您经常会看到类型为const string&的参数。为了性能目的而在内部执行此操作不会创建字符串的副本。
答案 5 :(得分:2)
int* ptr=#
第一种情况:由于ptr是一个内存,它存储一个变量的地址。 & operator返回内存中num的地址。
void DoSomething(string& str)
第二种情况:“&”运算符用于表示变量是通过引用传递的,可以通过函数进行更改。
所以基本上&运算符有2个函数,具体取决于上下文。
答案 6 :(得分:1)
虽然通过引用传递可以由编译器通过将地址作为指针传递来实现,但在语义上它与地址或指针无关。简单来说,它只是变量的别名。
C ++有很多情况下语法在具有不同语义的不同上下文中重用,这是其中一种情况。
答案 7 :(得分:1)
以下情况:
int* ptr=#
您声明一个名为ptr
的变量,其类型为int *
(int指针),并将其值设置为“变量num的地址”(&num
)。 “addressof”运算符(&
)返回一个指针。
以下情况:
void DoSomething(string& str)
您声明DoSomething()方法的第一个参数是“对字符串的引用”类型。实际上,这是定义“传递引用”的C ++方式。
请注意,虽然&
运算符在这些情况下同样运行 ,但它的行为方式并不相同。具体来说,当用作运算符时,您告诉编译器获取指定变量的地址;当在方法签名中使用时,您告诉编译器该参数是引用。并且还要注意,“作为引用的参数”位与具有指针的参数不同;引用参数(&
)会自动解除引用,并且永远不会对方法有任何关于底层数据存储位置的信息;使用指针参数,您仍然通过引用传递,但是您正在暴露存储变量的方法,并且如果方法无法取消引用(可能比您想象的更频繁地发生),则可能会暴露问题。
答案 8 :(得分:0)
你从copy
隐晦地复制str
。是的,str
是一个引用,但这并不意味着您无法从中构造另一个对象。在c ++中,&
运算符意味着三件事之一 -
&
的最后一个(对你的案例来说无关紧要)是按位AND。考虑引用的另一种方法(虽然稍微不正确)是解除引用指针的语法糖。