понедельник, 16 августа 2010 г.

Передавайте параметры по значению или по константной ссылке

Всем известно, что лучше избегать передачу параметров по ссылке, но повторение - мать учения! Последнюю пару недель работал с чужим кодом. Автор пренебрег данным наставлением, и частенько практикует передачу параметров по ссылке. Поломал же я голову над этим кодом, что вылилось в хороший пример. Давайте рассмотрим следующий код:

int number = 0;
for (RecordVector::const_iterator it = records.begin();
  it != records.end(); ++it)
{
  SaveRecord(writer, *it, number);
}

Как Вы думаете, что здесь происходит интересного? В цикле сохраняются какие-то записи, при чем для каждой указывается некий номер number. Только вот незадача, number нигде не изменяется! Бессмыслица какая-то... автор не ведал что писал? И тогда начинает рождаться догадка. Надо посмотреть объявление функции SaveRecord. Это ключевой момент. Смотрим:

void SaveRecord(WriterPtr writer, const Record& value, int& number);

Ага! Предположения оправдались. Параметр number передается по ссылке и меняется где-то в недрах функции. Теперь все встало на свои места.
Вывод: передача параметра по ссылке усложнила понимание кода, пришлось смотреть объявление функции, следовательно, пришлось отвлечься и потратить время. А из-за большого количества параметров, длинных названий типов, namespace'ов, даже посмотрев сигнатуру функции, можно упустить ссылку из виду. Например, следующий код, легче для понимания:

int number = 0;
for (RecordVector::const_iterator it = records.begin();
  it != records.end(); ++it)
{
  SaveRecord(writer, *it, number);
  number = CalculateNextNumber(...);
}

Другие примером, является функция, которая кроме того, что возвращает значение, так еще и параметр изменяет. Ладно бы процедура (функция, которая возвращает void; кто писал на Pascal'е знает), но функция выносит мозг.

FruitPtr Gather(const Tree& source, FruitIdType& id);

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

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

1 комментарий:

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

    ОтветитьУдалить