Передать по значению / указателю / уточнению ссылки

Мне нужно раз и навсегда уточнить прохождение значения / указателя / ссылки.

Если у меня есть переменная, такая как

int SomeInt = 10;

И я хочу передать это функции, как

void DoSomething(int Integer)
{
Integer = 1;
}

В моем текущем сценарии при передаче SomeInt в DoSomething () я хочу, чтобы значение SomeInt обновлялось в зависимости от того, что мы делаем с ним внутри DoSomething (), а также было наиболее эффективным с точки зрения памяти и производительности, поэтому я не копирую переменную вокруг? , При этом, какой из следующих прототипов будет выполнять эту задачу?

void DoSomething(int* Integer);
void DoSomething(int& Integer);

Как бы я на самом деле передать переменную в функцию? В чем разница между двумя предыдущими прототипами?

Наконец, если использовать функцию в классе

class SomeClass
{
int MyInteger;

public:
void ChangeValue(int& NewValue)
{
MyInteger = NewValue;
}
};

Если я передам целое число в ChangeValue, когда целое число, которое я передал в get, будет удалено, будет ли это означать, что когда я попытаюсь использовать MyInteger из класса, он больше не будет использоваться?

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

-5

Решение

Функционально все эти три работы:

  • передать int а также изменить тип возврата в int так что вы можете вернуть новое значение, использование: x = f(x);

    • когда вы планируете установить значение без необходимости читать начальное значение, гораздо лучше использовать такую ​​функцию, как int DoSomething(); так что звонящий может просто сказать int x = f(); без необходимости создавать x на более ранней линии и интересуясь / волнуясь, нужно ли его инициализировать чем-либо перед вызовом.
  • передать int& и установите его внутри функции, используя: int x; x = ? /* if an input */; f(x);

  • передать int* и установить на int внутри функции, использование: int x; x = ?; f(&x);

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

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

Для int вы можете ожидать, что первая версия выше не будет медленнее, чем версия указателя, и, возможно, будет быстрее, поскольку int Параметр может быть передан и возвращен в регистр без необходимости адреса памяти.

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

Тем не менее, если вам нужно задать вопрос, подобный этому, я не могу представить, что вы пишете код, в котором они являются важными вариантами оптимизации, поэтому лучшая цель — сделать то, что дает вам самое чистое, интуитивное и надежное использование для клиента. код … сейчас — будь то x = f(x); (где вы можете забыть ведущий x =), или же f(x) где вы можете не понимать x может быть изменено, или f(&x) (где некоторые абоненты могут подумать, что они могут пройти nullptr это разумный вопрос сам по себе, но отдельно от ваших проблем производительности. FWIW, C ++ FAQ Lite рекомендует ссылки на указатели для такой ситуации, но я лично отвергаю ее рассуждения и выводы — все сводится к знакомству с любым соглашением, и как часто вам нужно проходить const значения указателя или значения указателя, где nullptr является действительным стражем, который можно спутать с подразумеваемым в вашем сценарии выражением you-may-modify-me … которое во многом зависит от вашего стиля кодирования, используемых библиотек, проблемной области и т. д.

4

Другие решения

Оба ваших примера

void DoSomething(int* Integer);
void DoSomething(int& Integer);

выполнит задачу. В первом случае — с указателем — вам нужно вызвать функцию с DoSomething(&SomeInt);во втором случае — со ссылкой — проще как DoSomething(SomeInt);

Рекомендуемый способ — использовать ссылки, когда они достаточны, и указатели, только если они необходимы.

4

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

DoSomething(&SomeInt);

и для второго прототипа

DoSomething(SomeInt);
0

Как уже было сказано ранее, вы можете использовать оба. Преимущество

void DoSomething(int* Integer)
{
*Integer=0xDEADBEEF;
}
DoSomething(&myvariable);

шаблон заключается в том, что из вызова становится очевидным, что myvariable может быть изменен.

Преимущество

void DoSomething(int& Integer)
{
Integer=0xDEADBEEF;
}
DoSomething(myvariable);

шаблон в том, что код в DoSomething немного чище, DoSomething труднее связываться с памятью плохими способами, и вы можете получить из него лучший код. Недостатком является то, что после прочтения вызова не сразу видно, что myvariable может измениться.

0
По вопросам рекламы [email protected]