开发者

Use of the & operator in C++ function signatures

I'm currently reading through Accelerated C++ and I realized I don't really understand how & works in function signatures.

int* ptr=#

means that ptr now holds the address to num, but what does that mean?

void DoSomething(string& str)

from what I understand that is a pass by reference of a variable (which means passing the address) but when I do

v开发者_运维百科oid DoSomething(string& str)
{
  string copy=str;
}

what it creates is a copy of str. What I thought it would do is raise an error since I'm trying to assign a pointer to a variable.

What is happening here? And what is the meaning of using * and & in function calls?


A reference is not a pointer, they're different although they serve similar purpose. You can think of a reference as an alias to another variable, i.e. the second variable having the same address. It doesn't contain address itself, it just references the same portion of memory as the variable it's initialized from.

So

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.


The & character in C++ is dual purpose. It can mean (at least)

  1. Take the address of a value
  2. Declare a reference to a type

The use you're referring to in the function signature is an instance of #2. The parameter string& str is a reference to a string instance. This is not just limited to function signatures, it can occur in method bodies as well.

void Example() {
  string s1 = "example";
  string& s2 = s1;  // s2 is now a reference to s1
}

I would recommend checking out the C++ FAQ entry on references as it's a good introduction to them.

  • https://isocpp.org/wiki/faq/references


You shouldn't know anything about pointers until you get to chapter 10 of Accelerated C++ !

A reference creates another name, an alias, for something that exists elsewhere. That's it. There are no hidden pointers or addresses involved. Don't look behind the curtain!

Think of a guy named Robert

guy   Robert;

Sometimes you may want to call him Bob

guy& Bob = Robert;

Now Bob and Robert both refer to the same guy. You don't get his address (or phone number), just another name for the same thing.

In your function

void DoSomething(string& str)
{
  string copy=str;
}

it works exactly the same, str is another name for some string that exists somewhere else.

Don't bother with how that happens, just think of a reference as a name for some object. The compiler has to figure out how to connect the names, you don't have to.


In the case of assigning variables (ie, int* ptr = &value), using the ampersand will return the address of your variable (in this case, address of value).

In function parameters, using the ampersand means you're passing access, or reference, to the same physical area in memory of the variable (if you don't use it, a copy is sent instead). If you use an asterisk as part of the parameter, you're specifying that you're passing a variable pointer, which will achieve almost the same thing. The difference here is that with an ampersand you'll have direct access to the variable via the name, but if you pass a pointer, you'll have to deference that pointer to get and manipulate the actual value:

void increase1(int &value) {
   value++;
}

void increase2(int *value) {
   (*value)++;
} 

void increase3(int value) {
   value++;
}

Note that increase3 does nothing to the original value you pass it because only a copy is sent:

int main() {
   int number = 5;
   increase1(number);
   increase2(&number);
   increase3(number);
   return 0;
}

The value of number at the end of the 3 function calls is 7, not 8.


It's a reference which allows the function to modify the passed string, unlike a normal string parameter where modification would not affect the string passed to the function.

You will often see a parameter of type const string& which is done for performance purposes as a reference internally doesn't create a copy of the string.


int* ptr=#

1st case: Since ptr is a memory and it stores the address of a variable. The & operator returns the address of num in memory.

void DoSomething(string& str)

2nd case: The ampersand operator is used to show that the variable is being passed by reference and can be changed by the function.

So Basically the & operator has 2 functions depending on the context.


While pass by reference may be implemented by the compiler by passing the address as a pointer, semantically it has nothing to do with addresses or pointers. in simple terms it is merely an alias for a variable.

C++ has a lot of cases where syntax is reused in different contexts with different semantics and this is one of those cases.


In the case of:

int* ptr=#

you are declaring a variable named ptr with a type of an int * (int pointer), and setting its value to the "address of the variable num" (&num). The "addressof" operator (&) returns a pointer.

In the case of:

void DoSomething(string& str)

you are declaring the first parameter of the DoSomething() method to be of type "reference to string". Effectively, this is the C++ way of defining "pass-by-reference".

Note that while the & operator operates similarly in these cases, it's not acting in the same way. Specifically, when used as an operator, you're telling the compiler to take the address of the variable specified; when used in a method signature, you're telling the compiler that the argument is a reference. And note as well, that the "argument as a reference" bit is different from having an argument that is a pointer; the reference argument (&) gets dereferenced automatically, and there's never any exposure to the method as to where the underlying data is stored; with a pointer argument, you're still passing by reference, but you're exposing to the method where the variable is stored, and potentially exposing problems if the method fails to do a dereference (which happens more often than you might think).


You're inexplicitly copy-constructing copy from str. Yes, str is a reference, but that doesn't mean you can't construct another object from it. In c++, the & operator means one of 3 things -

  1. When you're defining a normal reference variable, you create an alias for an object.
  2. When you use it in a function paramater, it is passed by reference - you are also making an alias of an object, as apposed to a copy. You don't notice any difference in this case, because it basically is the object you passed to it. It does make a difference when the objects you pass contain pointers etc.
  3. The last (and mostly irrelevent to your case) meaning of & is the bitwise AND.

Another way to think about a reference (albeit slightly incorrect) is syntactic sugar for a dereferenced pointer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜