2010-12-13 2 views
23

Пропускает аргумент указателя, передает значение в C++? Поскольку я вижу, что любое изменение указателя как такового не отражается вне метода. Изменения, которые я делаю, разыменовывая указатель, отражены.Пропускает аргумент указателя, передает значение в C++?

В этом случае приемлемой/стандартной процедурой является использование указателя на указатель в качестве аргумента функции для изменения значения указателя как такового внутри функции?

+5

Указатель передается по значению, но объект, на который указывает указатель, может быть изменен функцией (зависит от const-qualification). – dreamlax

ответ

24

Да для обоих.

Указатели передаются по значению, как и все остальное. Это означает, что содержимое переменной указателя (адрес указанного объекта) копируется. Это означает, что если вы измените значение указателя в теле функции, это изменение не будет отражено во внешнем указателе, который все равно будет указывать на старый объект. Но вы можете изменить значение объекта, на который указывает.

Если вы хотите отразить изменения, внесенные в указатель на внешний указатель (чтобы он указывал на что-то еще), вам нужны два уровня косвенности (указатель на указатель). При вызове функций это делается путем помещения & перед именем указателя. Это стандартный способ делать вещи.

При использовании C++ использование ссылок предпочтительнее для указателя (далее также указатель на указатель).

Для том, почему ссылки предпочтения следует отдавать указатели, есть несколько причин:

  • ссылки ввести меньше syntaxic шума, чем указатели в теле функции
  • ссылки держать больше информации, чем указатели, чем может быть полезно для компилятора

недостатками ссылок в основном:

  • они нарушают простое правило передачи по значению C, что делает понимание поведения функции относительно параметров (они будут изменены?) Менее очевидны. Вам также нужен прототип функции. Но это не намного хуже, чем уровни множественного указателя, необходимые при использовании C.
  • они не поддерживаются C, это может быть проблемой при написании кода, который должен работать как с C, так и с C++-программами (но это не самый обычный случай).

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

+1

Почему для ссылок предпочтительнее использовать указатели? – Arafangion

+0

@Arafangion: Я отредактировал свой ответ, чтобы объяснить, почему предпочтения должны быть предпочтительнее указателей. – kriss

+0

Я предполагаю, что это субъективно - я предпочитаю использовать ссылки, потому что я переношу ответственность за проверку нулевого указателя на вызывающего абонента, и я обычно не забочусь о совместимости с C. Однако я не уверен, что я продаюсь на «Вам также нужны прототипы функций, чтобы убедиться, что значение не изменено» - это справедливо для многих классов C++ - они могут быть указателями сами и могут или не могут совместно использовать данные. Тем не менее, я предпочитаю переход по значению и позволяющий классу заботиться о любых указателях, если они необходимы, если только я не возвращаю ссылки rvalue, которые должны быть немедленно установлены, независимо, +1 – Arafangion

0

Либо указатель на указатель, либо ссылка на указатель - это то, что вы использовали бы, если бы захотели потенциально изменить сам указатель. По вашему первоначальному вопросу, технически, да, все параметры передаются по значению.

+7

«Все параметры передаются по значению» Нет, аргументы, переданные по ссылке, не передаются по значению. –

0

Да это, так как это в C.

В этом случае, это приемлемо/стандартная процедура, чтобы использовать указатель на указатель в качестве аргумента в функцию, чтобы изменить значение указателя в качестве таковых в пределах функции ?

В каком случае? Что ты хочешь?Вы можете использовать реальные ссылки с модификатором &.

void func(type &ref); 
6

Я понимаю путаницу здесь. Понятия «передать по значению» и «пройти по ссылке» не столь ясны, даже если они кажутся такими. Имейте в виду, что компьютер не знает эти понятия и не ведет себя в соответствии с ним. Компьютер не знает о типах. Следовательно, он не делает различия указателей и ценностей. Позвольте мне попытаться объяснить и пример:

void func1(int x) 
{ 
    x = 5; 
} 

void func2(int *x) 
{ 
    int a; 
    x = &a; 
} 

операция одинакова для машины в обе функции: он получает аргумент и изменяет его. Обратите внимание, что во второй функции он не модифицируется * x, он изменяет x.

Теперь, если мы называем эти функции,

int y = 10; 

func1(y); //value of y does not change 

func2(&y); //value of &y does not change, but the value of the address which y points may change. 

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

Если бы мы написали func2 в

void func2(int *x) 
{ 
    *x = 5; 
} 

Тогда это будет реальный случай «вызова по ссылке».