'&' 在 C++ 声明中有什么作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1943276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does '&' do in a C++ declaration?
提问by poundifdef
I am a C guy and I'm trying to understand some C++ code. I have the following function declaration:
我是一个 C 人,我正在尝试理解一些 C++ 代码。我有以下函数声明:
int foo(const string &myname) {
cout << "called foo for: " << myname << endl;
return 0;
}
How does the function signature differ from the equivalent C:
函数签名与等效的 C 有何不同:
int foo(const char *myname)
Is there a difference between using string *myname
vs string &myname
? What is the difference between &
in C++ and *
in C to indicate pointers?
使用string *myname
vs有区别string &myname
吗?&
C++ 和*
C 中指示指针的区别是什么?
Similarly:
相似地:
const string &GetMethodName() { ... }
What is the &
doing here? Is there some website that explains how &
is used differently in C vs C++?
什么是&
这里做什么?是否有一些网站解释了&
C 与 C++ 中的使用方式不同?
采纳答案by czuger
The "&" denotes a reference instead of a pointer to an object (In your case a constant reference).
“&”表示引用而不是指向对象的指针(在您的情况下是常量引用)。
The advantage of having a function such as
具有以下功能的优点
foo(string const& myname)
over
超过
foo(string const* myname)
is that in the former case you are guaranteed that myname is non-null, since C++ does not allow NULL references. Since you are passing by reference, the object is not copied, just like if you were passing a pointer.
是在前一种情况下,您可以保证 myname 是非空的,因为 C++ 不允许 NULL 引用。由于您是通过引用传递,因此不会复制对象,就像传递指针一样。
Your second example:
你的第二个例子:
const string &GetMethodName() { ... }
Would allow you to return a constant reference to, for example, a member variable. This is useful if you do not wish a copy to be returned, and again be guaranteed that the value returned is non-null. As an example, the following allows you direct, read-only access:
将允许您返回对例如成员变量的常量引用。如果您不希望返回副本,并且再次保证返回的值是非空的,这将很有用。例如,以下内容允许您直接进行只读访问:
class A
{
public:
int bar() const {return someValue;}
//Big, expensive to copy class
}
class B
{
public:
A const& getA() { return mA;}
private:
A mA;
}
void someFunction()
{
B b = B();
//Access A, ability to call const functions on A
//No need to check for null, since reference is guaranteed to be valid.
int value = b.getA().bar();
}
You have to of course be careful to not return invalid references. Compilers will happily compile the following (depending on your warning level and how you treat warnings)
您当然必须小心不要返回无效的引用。编译器会很高兴地编译以下内容(取决于您的警告级别以及您如何处理警告)
int const& foo()
{
int a;
//This is very bad, returning reference to something on the stack. This will
//crash at runtime.
return a;
}
Basically, it is your responsibility to ensure that whatever you are returning a reference to is actually valid.
基本上,您有责任确保您返回的引用实际上是有效的。
回答by Victor Nicollet
Here, &
is not used as an operator. As part of function or variable declarations, &
denotes a reference. The C++ FAQ Lite has a pretty nifty chapter on references.
在这里,&
不用作运算符。作为函数或变量声明的一部分,&
表示引用。C++ FAQ Lite 有一个非常漂亮的关于参考的章节。
回答by sohum
string * and string& differ in a couple of ways. First of all, the pointer points to the address location of the data. The reference points to the data. If you had the following function:
string * 和 string& 在几个方面有所不同。首先,指针指向数据的地址位置。引用指向数据。如果您有以下功能:
int foo(string *param1);
You would have to check in the function declaration to make sure that param1 pointed to a valid location. Comparatively:
您必须检查函数声明以确保 param1 指向有效位置。比较:
int foo(string ¶m1);
Here, it is the caller's responsibility to make sure the pointed to data is valid. You can't pass a "NULL" value, for example, int he second function above.
在这里,调用者有责任确保指向的数据有效。您不能传递“NULL”值,例如,上面的第二个函数。
With regards to your second question, about the method return values being a reference, consider the following three functions:
关于您的第二个问题,关于方法返回值是引用,请考虑以下三个函数:
string &foo();
string *foo();
string foo();
In the first case, you would be returning a reference to the data. If your function declaration looked like this:
在第一种情况下,您将返回对数据的引用。如果您的函数声明如下所示:
string &foo()
{
string localString = "Hello!";
return localString;
}
You would probably get some compiler errors, since you are returning a reference to a string that was initialized in the stack for that function. On the function return, that data location is no longer valid. Typically, you would want to return a reference to a class member or something like that.
您可能会遇到一些编译器错误,因为您要返回对在堆栈中为该函数初始化的字符串的引用。在函数返回时,该数据位置不再有效。通常,您希望返回对类成员或类似对象的引用。
The second function above returns a pointer in actual memory, so it would stay the same. You would have to check for NULL-pointers, though.
上面的第二个函数在实际内存中返回一个指针,所以它会保持不变。不过,您必须检查 NULL 指针。
Finally, in the third case, the data returned would be copied into the return value for the caller. So if your function was like this:
最后,在第三种情况下,返回的数据将被复制到调用者的返回值中。所以如果你的函数是这样的:
string foo()
{
string localString = "Hello!";
return localString;
}
You'd be okay, since the string "Hello" would be copied into the return value for that function, accessible in the caller's memory space.
你会没事的,因为字符串“Hello”将被复制到该函数的返回值中,可以在调用者的内存空间中访问。
回答by gavinb
Your function declares a constant referenceto a string:
您的函数声明了对字符串的常量引用:
int foo(const string &myname) {
cout << "called foo for: " << myname << endl;
return 0;
}
A reference has some special properties, which make it a safer alternative to pointers in many ways:
引用有一些特殊的属性,这使得它在很多方面都比指针更安全:
- it can never be NULL
- it must always be initialised
- it cannot be changed to refer to a different variable once set
- it can be used in exactly the same way as the variable to which it refers (which means you do not need to deference it like a pointer)
- 它永远不能为 NULL
- 它必须始终被初始化
- 一旦设置,就不能更改为引用不同的变量
- 它可以与它所引用的变量完全相同的方式使用(这意味着您不需要像指针一样尊重它)
How does the function signature differ from the equivalent C:
函数签名与等效的 C 有何不同:
int foo(const char *myname)
There are several differences, since the first refers directly to an object, while const char*
must be dereferenced to point to the data.
有几个区别,因为第一个直接const char*
引用一个对象,而必须取消引用才能指向数据。
Is there a difference between using string *myname vs string &myname?
使用字符串 *myname 与字符串 &myname 之间有区别吗?
The main difference when dealing with parameters is that you do not need to dereference &myname
. A simpler example is:
处理参数时的主要区别在于您不需要取消引用&myname
。一个更简单的例子是:
int add_ptr(int *x, int* y)
{
return *x + *y;
}
int add_ref(int &x, int &y)
{
return x + y;
}
which do exactly the same thing. The only difference in this case is that you do not need to dereference x
and y
as they refer directly to the variables passed in.
做完全一样的事情。在这种情况下唯一的区别是您不需要取消引用x
,y
因为它们直接引用传入的变量。
const string &GetMethodName() { ... }
What is the & doing here? Is there some website that explains how & is used differently in C vs C++?
& 在这里做什么?是否有一些网站可以解释 & 在 C 与 C++ 中的使用方式不同?
This returns a constant reference to a string. So the caller gets to access the returned variable directly, but only in a read-only sense. This is sometimes used to return string data members without allocating extra memory.
这将返回对字符串的常量引用。因此调用者可以直接访问返回的变量,但仅限于只读。这有时用于在不分配额外内存的情况下返回字符串数据成员。
There are some subtleties with references - have a look at the C++ FAQ on Referencesfor some more details.
引用有一些微妙之处 - 请查看有关引用的C++ 常见问题解答以获取更多详细信息。
回答by Chinmay Kanchi
#include<iostream>
using namespace std;
int add(int &number);
int main ()
{
int number;
int result;
number=5;
cout << "The value of the variable number before calling the function : " << number << endl;
result=add(&number);
cout << "The value of the variable number after the function is returned : " << number << endl;
cout << "The value of result : " << result << endl;
return(0);
}
int add(int &p)
{
*p=*p+100;
return(*p);
}
This is invalid code on several counts. Running it through g++ gives:
这是在几个方面无效的代码。通过 g++ 运行它给出:
crap.cpp: In function ‘int main()':
crap.cpp:11: error: invalid initialization of non-const reference of type ‘int&' from a temporary of type ‘int*'
crap.cpp:3: error: in passing argument 1 of ‘int add(int&)'
crap.cpp: In function ‘int add(int&)':
crap.cpp:19: error: invalid type argument of ‘unary *'
crap.cpp:19: error: invalid type argument of ‘unary *'
crap.cpp:20: error: invalid type argument of ‘unary *'
A valid version of the code reads:
代码的有效版本如下:
#include<iostream>
using namespace std;
int add(int &number);
int main ()
{
int number;
int result;
number=5;
cout << "The value of the variable number before calling the function : " << number << endl;
result=add(number);
cout << "The value of the variable number after the function is returned : " << number << endl;
cout << "The value of result : " << result << endl;
return(0);
}
int add(int &p)
{
p=p+100;
return p;
}
What is happening here is that you are passing a variable "as is" to your function. This is roughly equivalent to:
这里发生的事情是您将变量“按原样”传递给您的函数。这大致相当于:
int add(int *p)
{
*p=*p+100;
return *p;
}
However, passing a reference to a function ensures that you cannot do things like pointer arithmetic with the reference. For example:
但是,传递对函数的引用可确保您无法使用该引用执行指针算术之类的操作。例如:
int add(int &p)
{
*p=*p+100;
return p;
}
is invalid.
是无效的。
If you mustuse a pointer to a reference, that has to be done explicitly:
如果您必须使用指向引用的指针,则必须明确地完成:
int add(int &p)
{
int* i = &p;
i=i+100L;
return *i;
}
Which on a test run gives (as expected) junk output:
在测试运行中给出(如预期的)垃圾输出:
The value of the variable number before calling the function : 5
The value of the variable number after the function is returned : 5
The value of result : 1399090792
回答by FryGuy
One way to look at the & (reference) operator in c++ is that is merely a syntactic sugar to a pointer. For example, the following are roughlyequivalent:
在 C++ 中查看 &(引用)运算符的一种方法是,它只是指向指针的语法糖。例如,以下内容大致等效:
void foo(int &x)
{
x = x + 1;
}
void foo(int *x)
{
*x = *x + 1;
}
The more useful is when you're dealing with a class, so that your methods turn from x->bar() to x.bar().
更有用的是当你处理一个类时,你的方法从 x->bar() 变成 x.bar()。
The reason I said roughlyis that using references imposes additional compile-time restrictions on what you can do with the reference, in order to protect you from some of the problems caused when dealing with pointers. For instance, you can't accidentally change the pointer, or use the pointer in any way other than to reference the singular object you've been passed.
我粗略地说的原因是,使用引用对您可以使用引用做什么施加了额外的编译时限制,以保护您免受处理指针时引起的一些问题。例如,您不能意外更改指针,或以任何方式使用指针,而不是引用您传递的单个对象。
回答by Carson Myers
In this context &
is causing the function to take stringname
by reference.
The difference between references and pointers is:
在这种情况下&
导致函数stringname
通过引用获取。引用和指针的区别是:
- When you take a reference to a variable, that reference isthe variable you referenced. You don't need to dereference it or anything, working with the reference is sematically equal to working with the referenced variable itself.
NULL
is not a valid value to a reference and will result in a compiler error. So generally, if you want to use an output parameter (or a pointer/reference in general) in a C++ function, and passing a null value to that parameter should be allowed, then use a pointer (or smart pointer, preferably). If passing a null value makes no sense for that function, use a reference.- You cannot 're-seat' a reference. While the value of a pointer can be changed to point at something else, a reference has no similar functionality. Once you take a variable by reference, you are effectively dealing with that variable directly. Just like you can't change the value of
a
by writingb = 4;
. A reference's value is the value of whatever it referenced.
- 当您引用一个变量时,该引用就是您引用的变量。您不需要取消引用它或任何东西,使用引用在语义上等同于使用引用的变量本身。
NULL
不是引用的有效值,将导致编译器错误。所以一般来说,如果您想在 C++ 函数中使用输出参数(或一般的指针/引用),并且应该允许将空值传递给该参数,那么请使用指针(或智能指针,最好)。如果传递空值对该函数没有意义,请使用引用。- 您不能“重新安装”参考。虽然指针的值可以更改为指向其他内容,但引用没有类似的功能。一旦通过引用获取变量,您就可以有效地直接处理该变量。就像您不能通过
a
编写b = 4;
. 引用的值是它引用的任何值。