Игнорирование результата возврата по ссылке из функции - PullRequest
6 голосов
/ 17 октября 2011

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

int CalculateStuff(int param1, int param2, int& result1, int& result2);

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

...
int dummy1, dummy2;
int result = CalculateStuff(100, 42, dummy1, dummy2);
... // do something with the result

Я хотел бы рассмотреть другой способ сделать то же самое без объявления фиктивных переменных:

int result = CalculateStuff(100, 42, *new int, *new int);

Это имеет утечку памяти (неприемлемо),но имеет преимущество в том, что мое намерение (игнорирование результатов) более четко, чем «фиктивные» имена.

Итак, что произойдет, если я напишу это следующим образом:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get());

это законно?Будут ли существовать временные целые числа при выполнении кода функции?Должен ли я использовать unique_ptr вместо auto_ptr?

(Пожалуйста, не предлагайте рефакторинг моего кода; я, вероятно, буду - но сначала я хочу понять, как это работает)

Ответы [ 6 ]

4 голосов
/ 17 октября 2011

Согласно Бьярне Страуструпу, если некоторые параметры являются необязательными, это идеальный случай для того, чтобы сделать их типом указателя, чтобы вы могли передать NULL, когда вам не нужно передавать аргументы для них:

int CalculateStuff(int param1, int param2, int * result1, int * result2);

И используйте:

int result = CalculateStuff(100, 42, NULL, NULL);

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

Конечнореализация CalculateStuff должна проверить параметры, если они NULL или нет.

4 голосов
/ 17 октября 2011

Это законно; auto_ptr объекты будут оставаться живыми до конца выражения (то есть вызова функции). Но это ужасно ужасно.

Просто перегрузите вашу функцию:

int CalculateStuff(int param1, int param2, int& result1, int& result2);
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2);
}
3 голосов
/ 17 октября 2011

Вы можете сделать класс, который обеспечивает неявное (или явное) преобразование в int&.

struct ignored
{
   int n;
   operator int&() { return n; }
};

n = CalculateStuff(a, b, ignored(), ignored());

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

3 голосов
/ 17 октября 2011

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

Iпервая версия (с dummy1 и dummy2) является наиболее прозрачной и, очевидно, правильной.

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

int CalculateStuff(int param1, int param2, int& result1, int& result2) {}

int CalculateStuff(int param1, int param2) {
  int unwanted1, unwanted2;
  return CalculateStuff(param1, param2, unwanted1, unwanted2);
}
3 голосов
/ 17 октября 2011

Рекомендуемый подход, если у вас есть контроль над этой функцией: вернуть std::tuple (или boost::tuple) со всеми результатами или написать перегрузку, которая не требует дополнительных переменных.

2 голосов
/ 17 октября 2011

Это законно, но не гарантируется не утечка памяти, см. Вопрос 3 здесь например.

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

...