Re[6]: Как можно было так протупить с const параметрами?
От: vsb Казахстан  
Дата: 22.08.22 05:01
Оценка:
Здравствуйте, Marty, Вы писали:

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


M>Не в любом. В твоей джаве все по ссылкам передается, и вот там, да, const имеет некоторый смысл.


В жаве нет передачи по ссылке. В жаве исключительно передача по значению. В жаве ссылок в языке вообще нет, только указатели.

> Ну и, я не помню, как там в джаве, но если в плюсах передавать указатель на интерфейс, да или просто на объект, то все его вызываемые методы должны быть const, если указатель объявлен как const. Это уже прорастает в интерфейс объекта. Особенно это весело, если это интерфейс, там обычно методы const'ом не обмазывают.


В С++ это выглядит как my_class * const mc.

vsb>>Вот открываю рандомный кусок в nginx-е. Ни параметры не меняются, ни 2 локальные переменные не меняются. Это норма.

M>Там две переменные, которые константы, считай, и вполне можно обойтись и без них. А то, что по указателю — меняется. А вот указатель сам — не const, хотя можно было бы так сделать (но зачем? Если ты его в функции случайно поменяешь — а поменять там, кроме как на ноль — особо и не на что — и сразу seg fault при повторном использовании, а если после использования — то вообще и не заметишь). И буквально одной функцией выше — там всё меняется —
M> https://github.com/nginx/nginx/blob/f7ea8c76b55f730daa3b63f5511feb564b44d901/src/http/ngx_http_request_body.c#L820. Такое впечатление, что ты этот случайно тыкнутый фрагмент долго и тщательно выбирал

Не выбирал. В твоем примере параметры не меняются. Из четырех локальных переменных только 1 меняется.

Если я непонятно выражаюсь, под константными параметрами я имею в ввиду исключительно неизменяемость самой переменной. А не тех данных, куда она указывает. Константность тех данных, куда она указывает, это вопрос более сложный. От С этого требовать точно не стоит.

В C++ вопрос стоит с какой-то стороны проще, т.к. там часто применяются ссылки, которые неизменяемы по своей природе.
Отредактировано 22.08.2022 5:13 vsb . Предыдущая версия . Еще …
Отредактировано 22.08.2022 5:10 vsb . Предыдущая версия .
Re[2]: Как можно было так протупить с const параметрами?
От: Barbar1an Украина  
Дата: 22.08.22 07:19
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, Barbar1an, Вы писали:


B>>соотв нада было вводить не const модификатор, которым теперь всё заср*но


АТ>О чем речь вообще?


АТ>Практика навешивать `const` на параметры функций, чтобы предотвратить из изменение, существует и в ней есть логика. Но распространена эта практика настолько мало, что можно говорить "этим никто не пользуется".


АТ>О каком "всё заср*но" может идти речь в такой ситуации? Где вы такое сумели найти?


дело в том что есть случаи когда вы вынуждены использовать конст, например чтобы литералы передавать без обворачивания в конструктор, классика — std::string
а заюзав одном есте такой конст вас потом компилятор заставит в кучу других методов напихать их
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Как можно было так протупить с const параметрами?
От: Went  
Дата: 22.08.22 09:48
Оценка: 8 (2) +1
Здравствуйте, Barbar1an, Вы писали:

B>в 99% случаях передаваемые параметры не меняются функцией в которую передаются

B>соотв нада было вводить не const модификатор, которым теперь всё заср*но, а сделать всё по умолчанию const, а то что меняется указывать через например mutable

По умолчанию параметры передаются по значению, то есть копируются, а это еще большая "константность", нежели просто указание const. То есть есть передача по ссылке, по константной ссылке и по значению. И последнее — самое иммутабельное, иммутабельней некуда просто. Передавать по const-значению (int foo(const int arg)) — это просто синтаксический оверхед, простите, не дающий никакой безопасности. Ну, разве что спасёт от описки неопытного программиста. Ты предлагаешь запретить менять формальные параметры? А зачем? С/C++ — не функциональный язык, незачем подражать парадигмам другого языка. Кстати, а как смувить формальный параметр, обозначенный как const? Объявлять его mutable?
Re[2]: Как можно было так протупить с const параметрами?
От: Barbar1an Украина  
Дата: 22.08.22 09:54
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, Barbar1an, Вы писали:


B>>в 99% случаях передаваемые параметры не меняются функцией в которую передаются

B>>соотв нада было вводить не const модификатор, которым теперь всё заср*но, а сделать всё по умолчанию const, а то что меняется указывать через например mutable

W>По умолчанию параметры передаются по значению, то есть копируются, а это еще большая "константность", нежели просто указание const. То есть есть передача по ссылке, по константной ссылке и по значению. И последнее — самое иммутабельное, иммутабельней некуда просто. Передавать по const-значению (int foo(const int arg)) — это просто синтаксический оверхед, простите, не дающий никакой безопасности. Ну, разве что спасёт от описки неопытного программиста. Ты предлагаешь запретить менять формальные параметры? А зачем? С/C++ — не функциональный язык, незачем подражать парадигмам другого языка. Кстати, а как смувить формальный параметр, обозначенный как const? Объявлять его mutable?


передача по значению совсем не "самое иммутабельное, иммутабельней некуда просто", все зависит от того какой у вас там copy и move конструкторы
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[2]: Как можно было так протупить с const параметрами?
От: sergii.p  
Дата: 22.08.22 10:11
Оценка: +2 -1
Здравствуйте, Went, Вы писали:

W>По умолчанию параметры передаются по значению, то есть копируются, а это еще большая "константность", нежели просто указание const. То есть есть передача по ссылке, по константной ссылке и по значению. И последнее — самое иммутабельное, иммутабельней некуда просто. Передавать по const-значению (int foo(const int arg)) — это просто синтаксический оверхед, простите, не дающий никакой безопасности. Ну, разве что спасёт от описки неопытного программиста. Ты предлагаешь запретить менять формальные параметры? А зачем? С/C++ — не функциональный язык, незачем подражать парадигмам другого языка. Кстати, а как смувить формальный параметр, обозначенный как const? Объявлять его mutable?


смысл такой же как и объявлять любую переменную const

foo(const int i) // объявляем, что i меняться нигде дальше не будет
{
    const int k = i; // тоже самое. 
    ... // и тут кода на тыщу строк, чтобы сполна могли насладиться бонусами const
}


А то, что нельзя мувать const объекты — это уже явная бага C++. Впрочем она растёт из "use after move".
Re[7]: Как можно было так протупить с const параметрами?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 22.08.22 10:19
Оценка:
Здравствуйте, vsb, Вы писали:

M>>Не в любом. В твоей джаве все по ссылкам передается, и вот там, да, const имеет некоторый смысл.


vsb>В жаве нет передачи по ссылке. В жаве исключительно передача по значению. В жаве ссылок в языке вообще нет, только указатели.


Ну, ссылка или указатель — не суть, эти различия только в плюсах, где есть между ними различие. Мне почему-то казалось, что в джаве указатели на объекты именуются ссылками, вроде их то так то этак именуют там


>> Ну и, я не помню, как там в джаве, но если в плюсах передавать указатель на интерфейс, да или просто на объект, то все его вызываемые методы должны быть const, если указатель объявлен как const. Это уже прорастает в интерфейс объекта. Особенно это весело, если это интерфейс, там обычно методы const'ом не обмазывают.


vsb>В С++ это выглядит как my_class * const mc.


Что именно в C++ так выглядит? Что за "это"?


vsb>Не выбирал. В твоем примере параметры не меняются. Из четырех локальных переменных только 1 меняется.


Ну ок, тут ты прав



vsb>Если я непонятно выражаюсь, под константными параметрами я имею в ввиду исключительно неизменяемость самой переменной. А не тех данных, куда она указывает. Константность тех данных, куда она указывает, это вопрос более сложный. От С этого требовать точно не стоит.


Контролировать неизменяемость передаваемой переменной нафик не нужно, так как это вылезает в публичный контракт, которому, по большому счету, должно быть пофиг на то, что делается внутри функции. Было бы полезно, если бы внутри реализации был бы механизм, позволяющий сказать, что все параметры функции — константные, кроме указанных явно.
Маньяк Робокряк колесит по городу
Re[3]: Как можно было так протупить с const параметрами?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 22.08.22 10:21
Оценка:
Здравствуйте, Barbar1an, Вы писали:

B>дело в том что есть случаи когда вы вынуждены использовать конст, например чтобы литералы передавать без обворачивания в конструктор, классика — std::string


Это если ты std::string по ссылке передаешь, если по значению — не нужен никакой конст


B>а заюзав одном есте такой конст вас потом компилятор заставит в кучу других методов напихать их


Обычно это происходит, когда ты методы помечаешь, как конст
Маньяк Робокряк колесит по городу
Re[8]: Как можно было так протупить с const параметрами?
От: vsb Казахстан  
Дата: 22.08.22 10:31
Оценка: 1 (1)
Здравствуйте, Marty, Вы писали:

M>>>Не в любом. В твоей джаве все по ссылкам передается, и вот там, да, const имеет некоторый смысл.


vsb>>В жаве нет передачи по ссылке. В жаве исключительно передача по значению. В жаве ссылок в языке вообще нет, только указатели.


M>Ну, ссылка или указатель — не суть, эти различия только в плюсах, где есть между ними различие. Мне почему-то казалось, что в джаве указатели на объекты именуются ссылками, вроде их то так то этак именуют там


Ну я считаю, что ссылка это неизменяемый указатель, что-то вроде alias-а. А так ты прав, именуют по-разному. Хотя судя по тому, что в языке есть NullPointerException, а не NullReferenceException, я лично считаю, что официально их следует называть указателями. С другой стороны арифметики указателей в жаве тоже нет. В общем не суть, но ссылки/указатели жавы на указатели C++ похожи больше, чем на ссылки C++.

>>> Ну и, я не помню, как там в джаве, но если в плюсах передавать указатель на интерфейс, да или просто на объект, то все его вызываемые методы должны быть const, если указатель объявлен как const. Это уже прорастает в интерфейс объекта. Особенно это весело, если это интерфейс, там обычно методы const'ом не обмазывают.


vsb>>В С++ это выглядит как my_class * const mc.


M>Что именно в C++ так выглядит? Что за "это"?


Объявление неизменяемого параметра функции. Ну или объявление неизменяемой переменной (не нравится мне это словосочетание, немасляное масло, но называть это "константой", наверное, тоже не корректно). Т.е. сама переменная mc не изменяема, но при этом можно вызывать неконстантные методы класса my_class.

vsb>>Если я непонятно выражаюсь, под константными параметрами я имею в ввиду исключительно неизменяемость самой переменной. А не тех данных, куда она указывает. Константность тех данных, куда она указывает, это вопрос более сложный. От С этого требовать точно не стоит.


M>Контролировать неизменяемость передаваемой переменной нафик не нужно, так как это вылезает в публичный контракт, которому, по большому счету, должно быть пофиг на то, что делается внутри функции. Было бы полезно, если бы внутри реализации был бы механизм, позволяющий сказать, что все параметры функции — константные, кроме указанных явно.


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

Но вообще, похоже, что ты не прав. Такая программка в онлайн-компиляторе никаких предупреждений не выдаёт.


class my_class {
};

void print_my_class(my_class *mc);

int main()
{
    print_my_class(0);

    return 0;
}

void print_my_class(my_class * const mc) {
}
Отредактировано 22.08.2022 10:36 vsb . Предыдущая версия . Еще …
Отредактировано 22.08.2022 10:32 vsb . Предыдущая версия .
Re[3]: Как можно было так протупить с const параметрами?
От: Went  
Дата: 22.08.22 10:51
Оценка:
Здравствуйте, Barbar1an, Вы писали:
B>передача по значению совсем не "самое иммутабельное, иммутабельней некуда просто", все зависит от того какой у вас там copy и move конструкторы
Тогда и неявное указание константности на передаваемые значения тоже не гарантирует никакой иммутабельности, все зависит от того, сколько вы mutable и const_cast-ов влупили во внешне константные методы передаваемого объекта.
Re[3]: Как можно было так протупить с const параметрами?
От: Went  
Дата: 22.08.22 10:56
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>смысл такой же как и объявлять любую переменную const...

Ну, нормальный программист не пишет код на тыщу строк, а если это где-то критично, и он почему-то путается, в тех местах можно уже и объявить константный параметр или даже константную ссылку на параметр, если не хочется детали в интерфейс функции тянуть.
Re: Как можно было так протупить с const параметрами?
От: B0FEE664  
Дата: 22.08.22 13:18
Оценка: 1 (1)
Памяти было мало, её расход экономили переиспользованием переменных.
И каждый день — без права на ошибку...
Re: Как можно было так протупить с const параметрами?
От: kov_serg Россия  
Дата: 22.08.22 14:42
Оценка: 5 (1)
Здравствуйте, Barbar1an, Вы писали:

B>в 99% случаях передаваемые параметры не меняются функцией в которую передаются

B>соотв нада было вводить не const модификатор, которым теперь всё заср*но, а сделать всё по умолчанию const, а то что меняется указывать через например mutable

По сравнению с постулатом что в программе нет ошибок, а если есть то виноват только программист и это UB — не константные параметры по умолчанию не значительная мелочь.
Re[3]: Как можно было так протупить с const параметрами?
От: Андрей Тарасевич Беларусь  
Дата: 22.08.22 18:31
Оценка:
Здравствуйте, DiPaolo, Вы писали:

АТ>>Практика навешивать `const` на параметры функций, чтобы предотвратить из изменение, существует и в ней есть логика. Но распространена эта практика настолько мало, что можно говорить "этим никто не пользуется".


АТ>>О каком "всё заср*но" может идти речь в такой ситуации? Где вы такое сумели найти?


DP>Да повсюду.


DP>В код-стайлах многих компаний прописано использования конст везде, где это возможно:


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

DP>Blender

DP>Unreal Engine
DP>Google

Из приведенных вам ссылок только первая относится к рассматриваемому вопросу. Во второй ничего на эту тему вообще нет. В третьей же рекомендуется полностью обратное (!): "For a function parameter passed by value, const has no effect on the caller, thus is not recommended in function declarations".

DP>Вот рекомендации от Страуструпа и Саттера в C++ Core Guidelines:

DP>https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#con-constants-and-immutability

По ссылке нет ничего, относящегося к рассматриваемому вопросу. Тема объявления самих параметров как `const` не упоминается вообще.

DP>Вот несколько рандомных примеров из ГитХаба, где часто встречаются конст:

DP>https://github.com/danmar/cppcheck/blob/main/lib/check.h
DP>https://github.com/abseil/abseil-cpp/blob/master/absl/hash/hash.h
DP>https://github.com/catchorg/Catch2/blob/devel/src/catch2/catch_session.hpp

И здесь я навскидку не вижу абсолютно ничего, относящегося к рассматриваемому вопросу.

Напомню, что речь не о `const` вообще и не о const-квалификации путей доступа через указатели или ссылки, а именно об объявлении самих параметров функций как `const`. То есть речь идет именно о о (пример из вашей первой ссылки):

oid func(const float param) { ... }


Еще раз: это разумно, но практически этим никто не пользуется. Что, кстати, и демонстрируют приведенные вами ссылки. А гугловский гайд даже открытым текстом призывает не делать этого.
Best regards,
Андрей Тарасевич
Re[4]: Как можно было так протупить с const параметрами?
От: DiPaolo Россия  
Дата: 22.08.22 18:51
Оценка:
Вы вводите в заблуждение: вы говорите про параметры, но подразумеваете параметры, передаваемые по значению.
Патриот здравого смысла
Re[5]: Как можно было так протупить с const параметрами?
От: T4r4sB Россия  
Дата: 22.08.22 19:07
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Поэтому концепция "const по умолчанию" является правильной.


Пиши на Русте
Re[3]: Как можно было так протупить с const параметрами?
От: T4r4sB Россия  
Дата: 22.08.22 19:12
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>А то, что нельзя мувать const объекты — это уже явная бага C++. Впрочем она растёт из "use after move".


Она растёт из того, что move это не мув, а что-то типа свапа с чистым объектом.
А чтоб запретить use after move, надо превратить кресты в Руст
Re[2]: Как можно было так протупить с const параметрами?
От: Shtole  
Дата: 22.08.22 19:28
Оценка:
Здравствуйте, Pzz, Вы писали:

B>>в 99% случаях передаваемые параметры не меняются функцией в которую передаются

B>>соотв нада было вводить не const модификатор, которым теперь всё заср*но, а сделать всё по умолчанию const, а то что меняется указывать через например mutable

Pzz>Legacy.


Постоянно слышу про «легаси», когда возникает вопрос, почему было принято самое корявое и уродливое из всех возможных решений.

Как бы, язык давно уже разделился на C++14, C++17, C++20. Вполне можно было бы ввести что-то типа 'use strict' #pragma strict.
Do you want to develop an app?
Re: Как можно было так протупить с const параметрами?
От: Shtole  
Дата: 22.08.22 19:34
Оценка:
Здравствуйте, Barbar1an, Вы писали:

B>в 99% случаях передаваемые параметры не меняются функцией в которую передаются

B>соотв нада было вводить не const модификатор, которым теперь всё заср*но, а сделать всё по умолчанию const, а то что меняется указывать через например mutable

Засрано, факт. Во многих местах код, написанный без этого, просто не пропустят. Считается, что он от этого «лучше». Но тогда возникает закономерный вопрос, почему в этом языке по умолчанию код получается «хуже».
Do you want to develop an app?
Re[2]: Как можно было так протупить с const параметрами?
От: DiPaolo Россия  
Дата: 22.08.22 20:22
Оценка: +1 -2
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).
Патриот здравого смысла
Отредактировано 23.08.2022 7:17 DiPaolo . Предыдущая версия .
Re[9]: Как можно было так протупить с const параметрами?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.08.22 06:37
Оценка:
Здравствуйте, vsb, Вы писали:


vsb>Но вообще, похоже, что ты не прав. Такая программка в онлайн-компиляторе никаких предупреждений не выдаёт.


Да, похоже. Интересно, не знал. Я всегда только ссылки и указуемое константными объявлял, и с подобным не сталкивался.

Но тут другой нюанс. Если мы все параметры в прототипе обмазали const'ами (которые кроме случая ссылок снаружи рояли не играют), а в реализации — убрали эти const (или — наоборот), то хоть с точки зрения компилятора это будет одно и то же, но для человека это будет выглядеть очень по разному, и это плохо.

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

void traverse_list( List *pHead )
{
    for(; pHead; pHead=pHead->next)
    {
    //...
    }
}

void vec_something( int n, const vector &vec )
{
    if (vec.empty())
        return;

    if (n<0)
        n = 0;

    if (n>=vec.size())
        n = vec.size();

    //...
}

void str_something( string s )
{
    s = trim(s);
    s = to_upper(s);

    //...
}


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