2011-12-01 2 views
3

Я знаю, что вопрос «когда указатель и когда ссылка» или «передать аргумент в функции по ссылке или передать по указателю» был задан несколько раз. Тем не менее, у меня создалось впечатление, что в нескольких случаях я читал: «Вы должны передать объект в функцию указателем, если хотите его изменить». Может ли кто-нибудь сказать, объяснить и оправдать, если последнее предложение полностью правильно?Передача объекта в качестве ссылки или указателя в функции

Или, другими словами, невозможно ли изменить объект посредством ссылки?

ответ

4

Вы должны передать объект как двойной указатель, если вы хотите, чтобы изменить то, что указатель указывает на, например, при перемещении объекта из одного места памяти в другое:

void foo (obj **x) { 
    delete *x; 
    obj *y = (obj *) some_new_address; 
    *x = y; // change what x points to 
} 
... 
obj *x = new obj(); 
foo(&obj); 
// obj now points to another location 

С помощью ссылки вы можете» Это сделать.

+6

Вы можете передать указатель по ссылке: 'void foo (obj * & x)' –

+0

ОК, но тогда вы все равно передаете указатель. Смешивание указателя и эталонной семантики может быть очень запутанным, ИМО. –

+4

@BlagovestBuyukliev: А? Здесь нет ничего смешанного. Вы ссылаетесь на указатель. Это намного проще, чем указатель на указатель. – GManNickG

0

Вы можете изменить свой объект в обоих направлениях по ссылке и по указателю. Если вы не хотите изменять, вы можете использовать модификатор const.

2

Приведенное вами предложение является нормативным, то есть оно говорит вам, что вы должны делать, а не то, что вы «можете» или «не можете» делать. Таким образом, это вопрос стиля и обсуждения. Я лично этого не принимаю.

Это, безусловно, возможно изменить объект с помощью ссылки (не const).

0

Чтобы передать переменную как параметр out, вы можете передать ее как ссылку, так и указатель. Попробуйте использовать указатели только в том случае, если переменная должна жить дольше, чем область. Напр. возвращая указатель от функции к вызываемому.

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

1

Конечно, можно изменить объект посредством ссылки. Может быть, предложение, которое вы цитируете, было о C, в котором нет ссылок?

В руководстве, как это:

  • Если вы хотите изменить аргумент, и вызывающий абонент не может предоставить ее, пройти мимо указателя (и передать NULL, 0 или nullptr для не объекта).
  • Если вы хотите изменить аргумент, и объект должен быть передан функции - передать по ссылке.
  • Если вы не хотите изменять аргумент, но вызывающий может его не предоставлять, передайте указатель const
  • В противном случае, если объект дорог, чтобы скопировать пропуск по ссылке const, если нет, перейдите по значению.
  • Новая функция - если вы хотите скопировать аргумент внутри функции (например, передать строку в конструкторе для инициализации поля), и вы используете компилятор, совместимый с C++ 11 (поддержка конструкторов перемещения), передайте по значению.
4

Для удобства я буду ссылаться на параметр, который будет изменен функцией как «out-param».

Исходящие параметры могут передаваться как неконстантные ссылки. Нет никаких технических причин. В стандартных библиотеках, например, std::swap принимает два параметра по ссылке и изменяет оба.

В прошлом я видел, как правило, в руководстве по стилю, что out-params должны передаваться указателем, а не ссылкой. Мотивация заключается в том, что некоторые люди [*] хотят вызвать вызов функции, который появляется, чтобы передать объект по значению, чтобы оставить объект неизменным. Это облегчает для них рассуждение о части кода, просто глядя на вызывающий код, без необходимости искать то, что фактически выполняет функция. Например:

int foo(int a) { 
    return a + 1; 
} 
int bar(int &a) { 
    return ++a; 
} 

Теперь данный int i = 0;, звонки foo(i) и bar(i) выглядеть точно так же, но один из них ведет себя как хороший, простой функции C, тогда как другая использует пройти по ссылке, чтобы изменить i ,

Некоторые люди [*] хотят эти различные вещи, чтобы быть явно отличается на месте вызова, поэтому они предпочитают писать bar(&i), чтобы понять, что i может быть изменен [**]. В принципе, они предпочли бы, чтобы C++ не содержал неконстантных ссылок в качестве параметров функции вообще.

Не обязательно что-то не так, что эти люди хотят делать. Вы можете, например, придерживаться его в случае std::swap, всегда используя вместо этого std::iter_swap. Но большинство руководств по стилю C++ не имеют такого правила.

[*], например Программисты

[**] На самом деле в моей bar функции, a является и в-парам и из-парам. Их предпочтительная функция int bar(int *pa); технически не имеет out-param, хотя для удобства они, вероятно, будут ссылаться на referand pa (то есть i) как out-param, и все знают, что это значит.

Смежные вопросы