когда мне нужно пройти по указателю (а не по ссылке)

Можете ли вы привести пример, когда я не могу передать аргумент по ссылке и мне нужно использовать указатель. Я нашел пример, но я не уверен.

Предположим, у вас есть класс D, производный от базового класса B. Вам нужен указатель, если вы хотите сделать это:

void function(B* b){...}
int main{
  D* d;
  function(d);
}

person Ruggero Turra    schedule 14.10.2010    source источник
comment
Вы можете использовать ссылку в своем примере.   -  person JoshD    schedule 15.10.2010
comment
совсем недавно я задал эквивалентный вопрос что касается полиморфизма"> stackoverflow.com/questions/3835741/   -  person pm100    schedule 15.10.2010


Ответы (8)


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

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

person André Caron    schedule 14.10.2010
comment
Кто-то может возразить, что даже тогда вам не нужен указатель, если вы пишете объект, который имеет состояние, допускающее значение NULL. Но что угодно. - person John Dibling; 15.10.2010
comment
Да, но не все объекты обнуляются, особенно если вы используете RAII :-) - person André Caron; 15.10.2010
comment
@John Dibling: я не фанат концепции Nullable (по крайней мере, встроенной), я предпочитаю хук boost::optional, чтобы различать по типу, что может и не может быть нулевым. - person Matthieu M.; 15.10.2010

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

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

  • нулевой указатель является действительным и значимым фактическим аргументом или

  • фактический аргумент уже является наиболее естественным указателем, или

  • вы собираетесь хранить этот указатель где-нибудь.

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

Ура и чт.,

person Cheers and hth. - Alf    schedule 14.10.2010
comment
+1 для фактического аргумента, скорее всего, уже указатель. Очевидным примером является то, что когда вы говорите об итерации, вас волнует не только то, где вы находитесь в последовательности, но и то, на какой объект в последовательности вы смотрите. Например. Заголовок stackoverflow.com/questions/3909784/ . - person Brian; 15.10.2010

Другой случай: если вещь, которую вы передаете, является последним аргументом перед varargs:

void fn1(A &a, ...); // Uh oh
void fn2(A *a, ...); // Good

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

person Michael    schedule 15.10.2010
comment
Стандарт говорит только о том, что переменные аргументы должны быть последним аргументом или, возможно, должен быть один предшествующий аргумент. Тип этого аргумента определенно не упоминается. - person Puppy; 16.10.2010
comment
Тип POD непосредственно перед ... не требуется с точки зрения объявления или определения функции, но необходимо получить эти аргументы с пользой, используя va_start(). 18.7p3: если параметр [из va_start] объявлен с функцией, массивом или ссылочным типом или с типом, несовместимым с типом, который получается при передаче аргумента, для которого нет параметра, поведение не определено . - person aschepler; 16.10.2010
comment
Кроме того, в этой ситуации я рекомендую создать неявное преобразование из class A в структуру POD, которая содержит указатель A*, и использовать его в качестве последнего именованного аргумента, чтобы пользователи могли вызывать функцию, как если бы первый тип аргумента был действительно A ( или соответствующую ссылку). - person aschepler; 16.10.2010
comment
Конечно. Проблема, с которой я столкнулся, заключалась в том, чтобы получить аргументы, а не объявить или даже вызвать функцию. Спасибо за разъяснение, почему это так, и за запись в MSVC++ 2005, неопределенные средства не работают в этом конкретном случае, если вы используете ссылку. - person Michael; 16.10.2010

Как правило, вы используете указатели для одной из двух вещей:

  • Возможность переназначения — вы не можете переназначить ссылку.
  • Нулевые указатели - нет такой вещи, как нулевая ссылка.

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

person Puppy    schedule 15.10.2010

Если вы хотите разрешить отсутствие объекта, вам нужно использовать указатели:

// This allows DoSomething to receive pointers to NULL, which cannot
// be done with references
void DoSomething(Something *pSomething)
{
  if (pSomething)
  {
    ...
  }
}

int main()
{
  Something *pSomething=NULL;

  DoSomething(pSomething);
}
person Michael Goldshteyn    schedule 14.10.2010
comment
вместо длинной функции if рассмотрим if (!pSomething) { return; } вверху :) - person Matthieu M.; 15.10.2010

http://www.daniweb.com/forums/thread216353.html

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

person Jacob Nelson    schedule 14.10.2010

единственная причина в том, что вам нужно передать null. То есть вы хотите вызвать функцию, говоря: «У меня нет ни одного из них»

person pm100    schedule 14.10.2010

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

Например, возьмем следующую функцию:

#include <iostream>
#include "math.h"

void myfun (double value, size_t nofloops, double (*function)(double))
   {
   std::cout << value << std::endl;
   for (size_t i=0;i<nofloops;++i)
      {
      value = function(value);
      std::cout << value << std::endl;
      }
   std::cout << "------------------" << std::endl;
   }

void main()
   {
   myfun(100,10,sin);
   myfun(100,10,cos);
   myfun(100,10,sqrt);
   }

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

person Patrick    schedule 14.10.2010
comment
-1 для void main, что недопустимо как в C, так и в C++ (и никогда не было допустимо ни в одном из языков). При передаче по ссылке: просто замените (*function) на (&function). Вот и все. :-) Cheers & hth., - person Cheers and hth. - Alf; 15.10.2010
comment
PS: Когда вы передаете функцию по ссылке, вы получаете очень странного зверя (вероятно, поэтому вы думали, что это невозможно сделать), ссылку только для чтения. Это не ссылка на const, но вы не можете присвоить ему значение. Поскольку вы не можете назначить функцию, и если вы думаете о ссылке как о просто псевдониме, другом имени, тогда это имеет смысл. - person Cheers and hth. - Alf; 15.10.2010
comment
Судя по всему, некоторые старые компиляторы C допускают использование void main. См. homepage.ntlworld.com/jonathan.deboynepollard/FGA. /. - person Patrick; 15.10.2010