Информация об изменениях

Сообщение Re[2]: Как можно было так протупить с const параметрами? от 22.08.2022 20:22

Изменено 23.08.2022 7:17 DiPaolo

Re[2]: Как можно было так протупить с const параметрами?
W>То есть есть передача по ссылке, по константной ссылке и по значению. И последнее — самое иммутабельное, иммутабельней некуда просто. Передавать по const-значению (int foo(const int arg)) — это просто синтаксический оверхед, простите, не дающий никакой безопасности. Ну, разве что спасёт от описки неопытного программиста. Ты предлагаешь запретить менять формальные параметры? А зачем?

Ситуация, когда изменяется входящий параметр, достаточно нелогичная. Входящие параметры по значению — это, считай, настройки, конфиг. И менять их — весьма нетипичная и даже в некоторой степени является воркэраундом. Надо тебе что-то повычислять — заведи свою переменную, куда скопируй входное значение. А потом меняй его как хочешь. Изменение входящих параметров 100% ведет к багам и это является заложенной тайм-бомбой.

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

Можно было бы возвращать несколько значений (tuple), и не исхитрялись бы со всякими там двойными указателями и in/out параметрами. Не надо было бы думать об оптимизации — и пихали бы все по значению — и пофиг на копирование.

Потому что еще раз: логически параметры функции — это ее настройки. Которые логически должны быть константами. Типа, у нас ест функция возведения в степень double pow(int a, int b). По сути, здесь a и b — это настройки, начальные условия для вычислений. Меняться они не должны, потому что это условия вычисления, ну как параметры математической функции.

Вот еще пример, почему не стоит изменять параметры:
RetCode ProcessBuffer(uint8_t *data, int size)
{
    // обработали 4 байта
    const auto startCode = getBytes(data, 4);
    data += 4;
    size -= 4;

    ...


    // а тут новый человек по незнанию/невнимательности и т.д. сделал
    // подсчет чек суммы, получив ошибку
    const auto checkSum = calcCheckSum(data, size);
}

RetCode ProcessBuffer(const uint8_t* const data, const int size)
{
    auto ptr = data;
    auto bytesLeft = size;

    // обработали 4 байта
    const auto startCode = getBytes(ptr, 4);
    ptr += 4;
    bytesLeft -= 4;

    ...


    // делаем подсчет чек-суммы на входящем наборе данных
    const auto checkSum = calcCheckSum(data, size);
}


На практике так конечно никто не пишет )) Но лично я отношусь к входящим параметрам как "к чужому" — не мне их менять, это стартовые условия для вычислений.
Re[2]: Как можно было так протупить с const параметрами?
W>То есть есть передача по ссылке, по константной ссылке и по значению. И последнее — самое иммутабельное, иммутабельней некуда просто. Передавать по const-значению (int foo(const int arg)) — это просто синтаксический оверхед, простите, не дающий никакой безопасности. Ну, разве что спасёт от описки неопытного программиста. Ты предлагаешь запретить менять формальные параметры? А зачем?

Ситуация, когда изменяется входящий параметр, достаточно нелогичная. Входящие параметры по значению — это, считай, настройки, конфиг. И менять их — весьма нетипичная и даже в некоторой степени является воркэраундом. Надо тебе что-то повычислять — заведи свою переменную, куда скопируй входное значение. А потом меняй его как хочешь. Изменение входящих параметров 100% ведет к багам и это является заложенной тайм-бомбой.

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

Можно было бы возвращать несколько значений (tuple), и не исхитрялись бы со всякими там двойными указателями и in/out параметрами. Не надо было бы думать об оптимизации — и пихали бы все по значению — и пофиг на копирование.

Потому что еще раз: логически параметры функции — это ее настройки. Которые логически должны быть константами. Типа, у нас ест функция возведения в степень double pow(int a, int b). По сути, здесь a и b — это настройки, начальные условия для вычислений. Меняться они не должны, потому что это условия вычисления, ну как параметры математической функции.

Вот еще пример, почему не стоит изменять параметры:
RetCode ProcessBuffer(uint8_t *data, int size)
{
    // обработали 4 байта
    const auto startCode = getBytes(data, 4);
    data += 4;
    size -= 4;

    ...


    // а тут новый человек по незнанию/невнимательности и т.д. сделал
    // подсчет чек суммы, получив ошибку
    const auto checkSum = calcCheckSum(data, size);
}

RetCode ProcessBuffer(const uint8_t* const data, const int size)
{
    auto ptr = data;
    auto bytesLeft = size;

    // обработали 4 байта
    const auto startCode = getBytes(ptr, 4);
    ptr += 4;
    bytesLeft -= 4;

    ...


    // делаем подсчет чек-суммы на входящем наборе данных
    const auto checkSum = calcCheckSum(data, size);
}


На практике так конечно никто не пишет )) Но лично я отношусь к входящим параметрам как "к чужому" — не мне их менять, это стартовые условия для вычислений.

Upd под "так" имелось ввиду ставить const перед параметрами по значению для встроенных типов данных. Типа, int pow(const int a, const int b).