S>Пока имя аргумента закоментировано, вы его не можете использовать. И не получаете никаких предупреждений от компилятора. S>Если аргумент вам таки нужен, то вы раскоментируете его имя. Если при этом забыли поиспользовать, то компилятор вам об этом напоминает.
В прототипе одно, в реализации — другое?
А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0
S>Если же в прологе функции делать так: S>
S>int main(int argc, char ** argv) {
S> (void)argc; // Старая школа.
S> std::ignore = argv; // Можно и молодежно.
S>}
S>
S>то вы теряете вменяемые предупреждения от компилятора, если забыли использовать параметр в коде.
Я ничего не теряю, потому что USED добавляю, когда всё уже реализовано
Ситуации, когда забыл использовать параметр — ни разу не встречал. Обычно параметры всё таки осознанно добавляются, и не используются обычно, когда есть какой-то общий интерфейс, и в его частичной реализации необходимости части параметров нет
M>>Да, не трудился. На автомате
S>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.
То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.
M>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0
Не устраивают комментарии вокруг имени, вообще уберите имя:
void f(int) {
...
}
M>Я ничего не теряю, потому что USED добавляю, когда всё уже реализовано
Ох, ё.
M>Или нет
Ох, ё-ё-ё.
А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
Здравствуйте, so5team, Вы писали:
S>То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.
ИМена в декларации интересуют программиста, который будет поддерживать код. Держать две разные версии одного и того же — весьма неудобно
M>>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0
S>Не устраивают комментарии вокруг имени, вообще уберите имя: S>
S>void f(int) {
S> ...
S>}
Приходим к тому, что у декларации и реализации записано по разному. Ну, или можно из декларации тоже всё убрать, отличная идея.
S>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД
Здравствуйте, Marty, Вы писали:
S>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
M>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД
С моей колокольни это видно так: научить можно лишь того, что хочет научится.
Здравствуйте, Marty, Вы писали:
M>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.
Для указателей использую плюсовые касты, для арифметики конструкторы.
Сишные касты для указателнй слишком жестоки, а для арифметических типов многовато скобок получается — он вам не Лисп!
M>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)
Здравствуйте, so5team, Вы писали:
S>>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
M>>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД
S>С моей колокольни это видно так: научить можно лишь того, что хочет научится.
А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Здравствуйте, andrey.desman, Вы писали:
M>>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.
AD>Для указателей использую плюсовые касты, для арифметики конструкторы. AD>Сишные касты для указателнй слишком жестоки, а для арифметических типов многовато скобок получается — он вам не Лисп!
На мой взгляд, абсолютно разумная позиция. К сожалению, ни кто из участников не привел таких простых и внятных аргументов
M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)
AD>Зачем искать касты?
Ну, я не знаю, любители плюсовых кастов говорят, что их искать проще
M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Да нет же: сишный каст — это НЕ абсолютное зло. И имеет право на существование. Но так как в плюсах итак дохрена мест, в которых можно отстрелить себе ноги, лучше сводить риски к минимуму. Опять же: это всего лишь рекомендации, дальше уж каждый делает как считает нужным.
Здравствуйте, Marty, Вы писали:
M>А я не просил меня учить
Усвоение новой информации это уже не учеба? Ну ОК, как уже было сказано, любитесь как хотите.
M>Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Если вы не заметили, я здесь один из двух человек (второй DiPaolo), который хоть что-то приводит в подтверждение своих слов и единственный, который делает это на конкретных примерах. Если это "предоставлять не хочет", то... Любитесь как хотите, опять же.
Здравствуйте, andrey.desman, Вы писали:
M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)
AD>Зачем искать касты?
Ну как же. Вот будет в интернете кто-то неправ не поверит тов.Marty, что приходится снимать константность с указателя. А ты такой "Хоп!" и простым grep-ом по исходникам обнаруживаешь места, где const_cast используется. Ну красота же!
Здравствуйте, Marty, Вы писали:
M>Или битовые операторы и операторы сдвига — они, как оказалось, возвращают int/int64, а не тот тип, который изначально участвует в выражении. Полечил сишными кастами.
Про целочисленное расширение (integral promotion) почитай
Здравствуйте, so5team, Вы писали:
S>У меня нет под рукой собственной ошибки (хотя компилятор несколько раз в год бьет по рукам в попытках неправильно использовать static_cast, особенно в обобщенном коде). Но вот хороший пример из Интернета:
Добавь reinterpret_cast
Здравствуйте, Marty, Вы писали:
M>Почему сишным кастом пользоваться плохо?
Ну потому что, как правило, сишный каст выполняет преобразование большей силы, чем это реально нужно. Соответственно, он идет в разрез с принципами типовой безопасности C++. Вообще, тема очень избитая, не хотелось бы начинать еще один холивар на эту тему.
M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так: M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>
M>Но можно и так: M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>
M>Во втором случае выражение гораздо менее наглядно, приходится скрипеть мозгами, чтобы понять, что там происходит.
Для простых типов такое преобразование эквивалентно C-style cast, но, на мой взгляд, обладает несколькими преимуществами:
1) его невозможно ПО ОШИБКЕ применить к ссылке, указателю или какому-то еще типу, состоящему из двух и более лексем
2) для объектов классов такая запись будет означать инициализацию через конструктор
3) как по мне, у этой записи более приятный вид как по сравнению с C-cast, так и по сравнению с C++-cast записями
Впрочем, все сказанное — это мое имхо, на истину в последней инстанции не претендую.
Здравствуйте, Marty, Вы писали:
M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Абсолютного зла в IT не бывает, это уже чисто твой полемический задор. Есть зло разного уровня зловредности.
Сишные касты 1) заменяются на плюсовые без проблем, и в ~90% случаев каждый — одним кастом. 2) Грепабельны. Этого достаточно, чтобы форсировать их применение для большинства случаев.
Ну и, естественно, нужен какой-то механизм оставлять сишные с явной пометкой "Here be dragons", как же без этого. Но полиси типа "допускать такое только когда убедишь коллегу-ревьюера" вполне эффективно.
Здравствуйте, netch80, Вы писали:
S>>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.
N>Только в куче случаев это недодумка самого языка. Начиная с обсуждённых тут плясок вокруг размерности и знаковости типов.
Я так понимаю, что аргумент защитников Си-шных кастов состоит в том, что когда приходится делать касты (как из-за недодумок языка, так и по другим причинам), то Си-шный каст может быть предпочтительным из-за того, что писать нужно меньше, чем при использовании static_cast/const_cast/reinterpret_cast. И вот с этим я не согласен в том плане, что язык уже предоставляет инструменты для уменьшения синтаксического оверхэда. И если даже касты мы вынуждены применять из-за недодумок языка, то у нас есть возможности написать код так, чтобы совсем уж ужасно он не выглядел.
Здравствуйте, _NN_, Вы писали:
_NN>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов. _NN>Например pointer_cast
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, _NN_, Вы писали:
_NN>>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов. _NN>>Например pointer_cast
.
M>Это чем же C-style или constructor style касты неоднородны в синтаксисе с пользовательскими приведениями типов?
Тем, что нельзя «перегрузить» для примитивных типов.
К примеру lexical_cast<int> , pointer_cast<int*> .
Как это сделать в стиле конструктора ?
Можно конечно через промежуточный объект и операцию преобразования:
PointerCast<int*>(ptr) с каким-нибудь operator int*().
Но тут у нас лишние сущности получаются.
Здравствуйте, so5team, Вы писали: BFE>>Рад, что вы ждёте конструктивной критики. S>Для конструктивной нужно, чтобы критик понимал предмет разговора. Так что нет, не жду.
Т.е. вы думаете, что ваш код никто не поймёт? BFE>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем? S>Да, это const std::byte*, приходящий извне.
Но зачем нарушать контракт про "const"? BFE>>Почему обращение к fresh_frame->data по индексу, а не по итератору? S>Потому что это Си-ный массив. Имитировать итераторы через вызовы std::begin/end не вижу смысла.
Почему "эмитировать"? То, что в данном случае итератор — это указатель, ничего не меняет. BFE>>Где assert(std::size(fresh_frame->data) == std::size(data_plane_sizes))? S>Во-первых, assert-ы -- это развлечение для тех, кто нуждается в песочнице под названием debug mode. В release они не работают, поэтому для меня они бесполезны.
Это дело вкуса. То, что assert-ы не работают в release — опасное заблуждение. S>Во-вторых, это гарантируется в принципе Upd: гарантируется, что (std::size(fresh_frame->data) >= std::size(data_plane_sizes)). By design, так сказать.
Если By design, то где static_assert? BFE>>Зачем столько вызовов ptr_cast? Не проще ли завести один указатель? S>Потому что исходный указатель, image_bytes, постоянно изменяется (это даже в приведенном кусочке видно). А по ходу дела его приходится приводить к std::uint8_t* (да, без const, такова специфика используемой внешней библиотеки). Можно было бы, конечно, вести сразу два указателя, image_bytes и второй, который имеет тип std::uint8_t. Но какой смысл дублировать одно и то же?
Чтобы не полагаться на оптимизатор. BFE>>Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов) S>Мне сложно представить откуда здесь может взяться утечка, т.к. этот фрагмент -- это получение указателя на функцию, которая ничего не делает. Данный указатель требуется для av_buffer_create в качестве "деаллокатора".
А то я не вижу! S>Но т.к. деаллокатор здесь не нужен, то и функция пуста.
Вот и хотелось бы понять почему деаллокатор не нужен.
Вот в этой строчке заказ памяти AVBuffer *buf = av_mallocz(sizeof(*buf));:
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags)
{
AVBufferRef *ret;
AVBuffer *buf = av_mallocz(sizeof(*buf)); // тут заказали память под AVBuffer if (!buf)
return NULL;
ret = buffer_create(buf, data, size, free, opaque, flags);
if (!ret) {
av_free(buf);
return NULL;
}
return ret;
}
смотрим дальше:
static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags)
{
AVBufferRef *ref = NULL;
buf->data = data;
buf->size = size;
buf->free = free ? free : av_buffer_default_free; // т.к. free не NULL, то она будет использована вместо av_buffer_default_free
buf->opaque = opaque;
atomic_init(&buf->refcount, 1);// очевидно подсчёт числа "ссылок", т.о. ниже идёт имитация intrusive смарт указателя
buf->flags = flags;
ref = av_mallocz(sizeof(*ref)); // заказали память под "ссылку"if (!ref)
return NULL;
ref->buffer = buf; // в "ссылку" положили указатель на объект AVBuffer. это, впрочем, не важно.
ref->data = data;
ref->size = size;
return ref;
}
Таким образом в av_mallocz заказывается память под объект типа AVBufferRef, но вот освобождения этой памяти нет. Следовательно: либо это утечка памяти, либо вы как-то подменили av_mallocz, но если посмотреть: