Использование оператора & в сигнатурах функций C ++ - PullRequest
22 голосов
/ 29 июля 2011

Я сейчас читаю через Accelerated C ++ и понял, что не совсем понимаю, как и как работают сигнатуры функций.

int* ptr=#

означает, что ptr теперь содержит адрес num, но что это значит?

void DoSomething(string& str)

из того, что я понимаю, это передача по ссылке на переменную (что означаетпередавая адрес), но когда я делаю

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

, он создает копию str.Я подумал, что это вызовет ошибку, поскольку я пытаюсь назначить указатель на переменную.

Что здесь происходит?И что означает использование * и & в вызовах функций?

Ответы [ 9 ]

35 голосов
/ 29 июля 2011

Ссылка - это , а не указатель, они разные, хотя служат одной и той же цели. Вы можете рассматривать ссылку как псевдоним другой переменной, то есть второй переменной, имеющей тот же адрес. Он не содержит самого адреса, он просто ссылается на ту же часть памяти, что и переменная, из которой он инициализирован.

Итак

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.
25 голосов
/ 29 июля 2011

Символ & в C ++ имеет двойное назначение.Это может означать (как минимум)

  1. Взять адрес значения
  2. Объявить ссылку на тип

Использование, на которое вы ссылаетесьв сигнатуре функции есть экземпляр # 2.Параметр string& str является ссылкой на экземпляр string.Это не ограничивается только сигнатурами функций, это может происходить и в телах методов.

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

Я бы порекомендовал проверить запись C ++ FAQ по ссылкам, поскольку это хорошее введение в них.

13 голосов
/ 29 июля 2011

Вы не должны знать ничего об указателях, пока не перейдете к главе 10 Ускоренного C ++!

Ссылка создает другое имя, псевдоним, для чего-то, что существует в другом месте. Вот и все. Здесь нет скрытых указателей или адресов. Не смотри за кулисы!

Подумайте о парне по имени Роберт

guy   Robert;

Иногда вы можете звать его Боб

guy& Bob = Robert;

Теперь Боб и Роберт оба относятся к одному и тому же парню. Вы не получаете его адрес (или номер телефона), просто другое имя для той же вещи.

В вашей функции

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

это работает точно так же, str - это другое имя для некоторой строки, которая существует где-то еще.

Не беспокойтесь о том, как это происходит, просто думайте о ссылке как об имени какого-то объекта. Компилятор должен выяснить, как соединять имена, вам не нужно.

11 голосов
/ 29 июля 2011

В случае назначения переменных (т. Е. 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;
}

Значение number в конце3 функциональных вызова - это 7, а не 8.

4 голосов
/ 29 июля 2011

Это ссылка, которая позволяет функции изменять переданную строку, в отличие от обычного строкового параметра, где изменение не повлияет на строку, переданную функции.

Вы часто увидите параметр типа const string &, который сделан для повышения производительности, поскольку внутренняя ссылка не создает копию строки.

2 голосов
/ 29 июля 2011
int* ptr=#

1-й случай: поскольку ptr - это память, в которой хранится адрес переменной. Оператор & возвращает адрес num в памяти.

void DoSomething(string& str)

2-й случай: оператор амперсанда используется, чтобы показать, что переменная передается по ссылке и может быть изменена функцией.

Так что в основном оператор & имеет 2 функции в зависимости от контекста.

1 голос
/ 29 июля 2011

В случае:

int* ptr=#

вы объявляете переменную с именем ptr с типом int * (указатель int) и присваиваете ей значение «адрес переменной num» (&num). Оператор addressof (&) возвращает указатель.

В случае:

void DoSomething(string& str)

вы объявляете первый параметр метода DoSomething () типа «ссылка на строку». По сути, это способ определения «передачи по ссылке» в C ++.

Обратите внимание, что хотя оператор & работает аналогично в этих случаях, он не действует аналогичным образом. В частности, при использовании в качестве оператора вы указываете компилятору взять адрес указанной переменной; при использовании в сигнатуре метода вы сообщаете компилятору, что аргумент является ссылкой. И заметьте также, что бит «аргумент как ссылка» отличается от аргумента, который является указателем; ссылочный аргумент (&) автоматически разыменовывается, и в методе никогда не указывается, где хранятся базовые данные; с аргументом указателя вы все еще передаете по ссылке, но вы открываете метод, в котором хранится переменная, и, возможно, обнаруживаете проблемы, если метод не может выполнить разыменование (что происходит чаще, чем вы думаете).

1 голос
/ 29 июля 2011

Хотя передача по ссылке может быть реализована компилятором путем передачи адреса в виде указателя, семантически он не имеет ничего общего с адресами или указателями.Проще говоря, это просто псевдоним для переменной.

C ++ имеет много случаев, когда синтаксис повторно используется в разных контекстах с различной семантикой, и это один из таких случаев.

0 голосов
/ 29 июля 2011

Вы неявным образом копируете copy из str.Да, str - это ссылка, но это не значит, что вы не можете создать из нее другой объект.В c ++ оператор & означает одну из трех вещей -

  1. Когда вы определяете нормальную ссылку переменная , вы создаете псевдоним дляобъект.
  2. Когда вы используете его в параметре функции, он передается по ссылке - вы также создаете псевдоним объекта по сравнению скопия.В этом случае вы не заметите никакой разницы, потому что в основном является объектом, который вы ему передали.Это действительно имеет значение, когда объекты, которые вы передаете, содержат указатели и т.д.1026 *

    Еще один способ подумать о ссылке (пусть и немного неправильной) - синтаксический сахар для разыменованного указателя.

...