Есть ли преимущества передачи по указателю над передачей по ссылке в C++?



каковы преимущества передачи по указателю над передачей по ссылке в C++?



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



пример:



func(SPRITE *x);


с вызовом на



func(&mySprite);


и



func(SPRITE &x);


с вызовом на



func(mySprite);
596   6  

6 ответов:

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

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

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

проходя мимо указателя

  • вызывающий должен принять адрес - > не прозрачный
  • значение 0 может быть указано какnothing. Это можно использовать для предоставления дополнительных аргументов.

проходим по ссылке

  • вызывающий просто передает объект - > прозрачный. Должен использоваться для перегрузки операторов, так как перегрузка для типов указателей невозможна (указатели являются встроенными типами). Так что вы не можете сделать string s = &str1 + &str2; С помощью указателей.
  • нет 0 возможных значений - > вызываемая функция не должна проверять их
  • ссылка на const также принимает временные конструкции: void f(const T& t); ... f(T(a, b, c)); указатели не могут быть использованы с тех пор, как вы не можете взять адрес временного.
  • и последнее, но не менее важное: ссылки легче использовать -> меньше шансов на ошибки.

Аллен Голуб "достаточно веревки, чтобы выстрелить себе в ногу" перечисляет следующие 2 правила:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

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

  • они необходимы для определения конструкторов копирования
  • они необходимы для перегрузок оператора
  • const ссылки позволяют вам иметь семантику передачи по значению, избегая копирования

его главный смысл заключается в том, что ссылки не должны использоваться в качестве "выходные" параметры, потому что на сайте вызова нет указания, является ли параметр ссылкой или параметром значения. Так что его правило-использовать только const ссылки в качестве аргументов.

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

Мне нравится рассуждение по статье из "cplusplus.com:"

  1. передать значение, когда функция не хочет изменять параметр и значение легко скопировать (ints, Double, char, bool и т. д... простейший тип. std::string, std:: vector и все другие контейнеры STL не являются простыми типами.)

  2. Pass by const указатель, когда значение дорого для копирования и функция не хочет изменять значение, на которое указывает и NULL-допустимое, ожидаемое значение, которое обрабатывает функция.

  3. Pass by non-const указатель, когда значение дорого для копирования и функция хочет изменить значение, на которое указывает и NULL является допустимым, ожидаемое значение, которое обрабатывает функция.

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

  5. Pass by non-cont reference, когда значение дорого копировать, и функция хочет изменить значение, на которое ссылается, и NULL не будет допустимым значением, если вместо этого использовался указатель.

  6. при написании функций шаблона нет четкого ответа, потому что есть несколько компромиссов, которые выходят за рамки этого обсуждения, но достаточно сказать, что большинство функций шаблона принимают свои параметры значение или (const) ссылка, однако, поскольку синтаксис итератора аналогичен синтаксису указателей (Звездочка для "разыменования"), любая функция шаблона, которая ожидает итераторы в качестве аргументов, также по умолчанию будет принимать указатели (и не проверять значение NULL, поскольку концепция нулевого итератора имеет другой синтаксис).

http://www.cplusplus.com/articles/z6vU7k9E/

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

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

пояснения к предыдущим постам:


ссылки не гарантия получения ненулевого указателя. (Хотя мы часто относимся к ним именно так.)

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

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

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

вдруг есть мир разницы между foo (BAR bar) и foo (BAR & бар). (Вызывается автоматическая побитовая операция копирования. Освобождение в деструкторе вызывается дважды.)

к счастью, современные компиляторы будет забрать двойное освобождение одного и того же указателя. 15 лет назад они этого не сделали. (под gcc / g++ используйте setenv MALLOC_CHECK_ 0 вернуться к старым привычкам.) В результате, в соответствии с DEC UNIX, в одной и той же памяти выделяются два разных объекта. Там много удовольствия от отладки...


более практически:

  • ссылки скрывать, что вы меняете данные, хранящиеся в другом месте.
  • легко перепутать ссылку с копируемой объект.
  • указатели делают это очевидным!

Не совсем так. Внутренне передача по ссылке выполняется, по существу, передавая адрес объекта ссылки. Таким образом, на самом деле нет никакого повышения эффективности, которое можно получить, передав указатель.

передача по ссылке имеет одно преимущество, однако. Вы гарантированно имеете экземпляр любого объекта/типа, который передается. Если вы передаете указатель, то вы рискуете получить нулевой указатель. Используя pass-by-reference, вы нажимаете неявное значение NULL-проверьте один уровень вызывающей функции.

Comments

    Ничего не найдено.