Подтвердить что ты не робот

Когда pass-by-pointer предпочтительнее передавать по ссылке в С++?

Я могу представить один случай, в котором входной параметр может быть NULL, так что по-указателю предпочтительнее, но не по-ссылке?

Может ли кто-нибудь добавить больше случаев?

4b9b3361

Ответ 1

Некоторым, таким как pass-by-pointer, лучше в тех случаях, когда передаваемый объект на самом деле будет изменен. Они используют pass-by-const-reference, когда объект передается ссылкой, чтобы избежать копирования объекта, но не будет изменяться в функции.

В качестве иллюстрации выполните следующие функции:

int foo(int x);
int foo1(int &x);
int foo2(int *x);

Теперь в коде я делаю следующее:

int testInt = 0;

foo(testInt);   // can't modify testInt
foo1(testInt);  // can modify testInt

foo2(&testInt); // can modify testInt

При вызове foo vs foo1 это не очевидно с точки зрения вызывающих (или программистов, читающих код), что функция может изменять testInt, не глядя на подпись функции. Глядя на foo2, читатель может легко увидеть, что функция может фактически изменить значение testInt, потому что функция получает адрес параметра. Обратите внимание, что это не гарантирует, что объект фактически изменен, но тот, который помогает в использовании ссылок или указателей. В общем, если вы хотите последовательно следовать этому руководству, вы всегда должны передавать ссылки const, когда хотите избежать копирования, и передавать указатель, когда хотите изменить объект.

Ответ 2

С++ FAQ имеет очень хороший ответ на этот вопрос:

Используйте ссылки, когда можете, и указатели, когда вам нужно.

Ссылки обычно предпочтительнее указатели, когда вам не нужны "Переустановка". Это обычно означает, что ссылки наиболее полезны в класса. Рекомендации обычно появляются на коже объект и указатели внутри.

Исключением из вышеприведенного является то, что параметр функции или возвращаемое значение нуждается в "контрольной" ссылке - a ссылка, которая не относится к объект. Обычно это лучше всего делать возвращая/беря указатель и давая указатель NULL этот специальный значимость (ссылки всегда должны псевдонимы, а не NULL с разыменованием указатель).

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

Ответ 3

У вас много ситуаций в программировании реального мира, где параметр не существует или является недопустимым, и это может зависеть от семантики кода выполнения. В таких ситуациях вы можете использовать NULL (0) для сигнализации этого состояния. Кроме того,

  • Указатель может быть переназначен новым государство. Ссылка не может. Это желательно в некоторых ситуациях.
  • Указатель помогает переносить владельца семантика. Это особенно полезно в многопоточной среде, если Состояние параметра используется для выполнения в отдельный поток, и вы не обычно проводят опрос до тех пор, пока вышел.

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

Ответ 4

В дополнение к некоторым другим ответам о семантике собственности (особенно функции factory).

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

void Operate(const int &input_arg, int *output_arg) {
  *output_arg = input_arg + 1;
}

int main() {
  int input_arg = 5;
  int output_arg;
  Foo(input_arg, &output_arg);  // Passing address, will be modified!
}

Ответ 5

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

Обоснование, если оно не может (не должно!) когда-либо быть NULL, тогда не ставьте себя на проблему с проверкой NULL или риском проблем из-за того, что он является NULL.

Ответ 6

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

Ответ 7

В С++ в большинстве случаев мало нужно пропускать указатель. Сначала вы должны рассмотреть альтернативы: шаблоны, (const) ссылки, контейнеры, строки и интеллектуальные указатели. Тем не менее, если вы должны поддерживать устаревший код, вам нужно будет использовать указатели. Если ваш компилятор минималистичен (например, встроенные системы), вам понадобятся указатели. Если вам нужно поговорить с библиотекой C (какая-то системная библиотека для определенного драйвера, с которым вы работаете?), Вам нужно будет работать с указателями. Если вы хотите иметь дело с очень специфическими смещениями памяти, вам понадобятся указатели.

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

Ответ 8

Каждый раз, когда вы передаете указатель на функцию. Или если у вас есть метод "reset" a la auto_ptr.

Ответ 9

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

Например:


void f( int* p )
{
    // ..

    delete []p;
    p = new int[ size ];

    //...
}

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

Ответ 10

Это не конкретная передача аргументов, но она влияет на передачу аргументов.

У вас может быть контейнер/совокупность указателей, но не ссылок. Хотя ссылки являются полиморфными, только указатели поддерживают операцию "обновления", которая необходима для использования в контейнере (тем более, что вы еще не можете инициализировать ссылки в массовом порядке, не уверены, изменит ли это инициализаторы С++ 0x).

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

Ответ 11

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

Ответ 12

Если мне нужно передать массив объектов, мне нужно пройти по указателю. Массивы не всегда хранятся в std::vector<>.

Кроме этого, pass by pointer позволяет NULL и передавать по ссылке, нет, поэтому я использую это различие как контракт, похожий на столбцы NULL vs. NOT NULL в SQL, а также как функция return bool: true= удалось и false= не удалось, vs. function return int: return value - это код результата, где 0= успех, а другие - сбои ".