Задать вопрос
  • Важен ли return в main?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Формально, единственная функция, в которой можно не делать return - это именно main.

    В остальных случаях, если функция что-то возвращает, наличие return обязательно - иначе будет UB.

    Почему для main исключение - никто не знает, потому что параграф в стандарте языка, на который ссылается другой параграф - потерялся:

    I looked it up. I believe this was introduced with C99, and apparently the C99 rationale is defect. It has comments for 5.1.2.2.1 Program startup, then labels the next chapter 5.1.2.3 Program execution. It should have been 5.1.2.2. As a consequence of this, the rationale for Program termination that should have been in the real chapter 5.1.2.3, has gone missing in action. Thus, main allows no return code in C99 and there exists no rational reason why.


    Источник
    Ответ написан
    Комментировать
  • Как очистить выделенную память адреса под адрес указателя на первый элемент строки?

    Adamos
    @Adamos
    // выделяется память размером с указатель (4/8 байт для x32/x64), ее адрес записывается в text
    text = (const char**)malloc(sizeof(char*));
    // в text записывается адрес другой строки, а где там была выделена память - больше никто не знает
    text = &smth;
    // освобождается та память, на которую указывает text - это переменная smth. Теперь память, в которой лежит эта переменная, может в любой момент быть заменена при новом выделении памяти, и smth получит новое значение, не имеющее никакого отношения к той строке, на которую оно указывало изначально
    free(text);
    Ответ написан
  • Assignment operator VS Destructor + Placement new, где аргумент placement new - prvalue?

    @dolusMalus
    С++ programmer from gamedev
    Мне кажется, что данный вопрос стоит рассмотреть с точки зрения нескольких позиций:
    1. Безопасность относительно исключений. Какой уровень гарантий должен предоставлять данный метод?
    2. Производительность. Критично ли получить максимально эффективный код или на данном этапе этим можно пожертвовать?
    3. Оценить проектное решение в свете известных и проверенных практик, например, принципы SOLID


    Для начала определяемся используются ли вообще исключения в Вашем проекте и если нет, то можно переходить сразу к вопросу о производительности. В противном случае, рассмотрим каждый случай:
    int32_t index = sizeof(T) * head;
            (reinterpret_cast<T *>(&buffer[index]))->~T();
            new (&buffer[index]) T(std::forward<Args>(args)...);
            head = (head + 1) % maxSize;

    данный вариант не предоставляет даже базовых гарантий (basic exception guarantee), т.к. если конструктор сгенерирует исключение, то мы уже закончили время жизни объекта вызвав деструктор, но не изменятся size и head; а значит мы пришли в невалидное состояние.

    int32_t index = sizeof(T) * head;
            (reinterpret_cast<T *>(&buffer[index]))->~T();
            new (&buffer[index]) T(std::forward<Args>(args)...);
            head = (head + 1) % maxSize;

    Можем сделать развилку по noexcept для конструктора с помощью SFINAE или if constexpr и в случае, если конструктор является noexcept; то оставить данный код. В противном случае придется уже действовать в зависимости от необходимого уровня гарантий, однако решения будут достаточно громоздкие: в добавок к развилке надо будет ловить исключение, пробрасывать его дальше, при этом восстанавливать объект или уменьшать счетчики и т.п. Более того можно вообще не обеспечить сильную гарантию при определенных условиях. Как видите, это уже сильно осложнило решение.
    Теперь к другому варианту:
    // Assignment operator
    //        (*(reinterpret_cast<T *>(&buffer[sizeof(T) * head]))) = T(std::forward<Args>(args)...);

    Здесь ситуация относительно лучше, т.к. проблемы могут быть только на уровне оператора присваивания, что как минимум перекладывает часть ответственности в сторону автора типа T. Однако воспользовавшись решением от Евгений Шатунов можно относительно легко получить достаточно понятный и "чистый" код на уровне сильных гарантий. Также стоит посмотреть в сторону copy and swap идиомы, как близкой к данной проблеме.
    По итогу при необходимости строгих гарантий стоит отдать предпочтение варианту с временным объектом.

    С точки зрения производительности, если нет необходимости в максимальной оптимизации, то стоит отдать предпочтение более понятному коду. Данный момент уже прекрасно освещен в ответе Евгений Шатунов, поэтому не вижу смысла повторяться. Однако формально если отбросить предположения об оптимизациях, то вариант с реконструированием по месту (деструктор -> конструктор) оптимальней, т.к. гарантировано не требует выделения дополнительных ресурсов от временного объекта и только две операции + нет необходимости в относительно сложном анализе на перемешаемость/копируемость. В случае со swap, мы можем таки попасть на копирование в зависимости от перемещаемости типа T.

    И часто забываемый, но крайне важный пункт про проектирование. Здесь нарушен Single responsibility принцип, что возможно и породило этот вопрос. Т.е. у Вас метод по добавлению элемента может удалять/заменять элементы, что должно вызвать вопросы. Более того, вы решили за клиента вашего API (даже если это и Вы сами) как нужно обрабатывать исключительную ситуацию по переполнению. Потом например вы решите, что в одном месте стоит сложить старые элементы в отдельную очередь в другом залогировать или удалять не по одному, а сразу половину буффера. Все это потребует переписывания метода add, а зачем и почему? Попробуйте убрать эту часть кода заменив на выбрасывание исключения или вариант с возвращением успешности операции (менее грамотное решение, но это уже из области субъективной оценки) и посмотреть как увеличится прозрачность и простота написания клиентского кода для этого метода. Еще стоит посмотреть на сходное проектное решение в std::vector и его методе pop_back. Подумайте почему он не возвращает удаленный элемент?

    Итого, если важна производительность и не важна работа с исключениями; то разумно выбрать вариант с реконструированием; иначе обмен с временным объектом. Но не стоит забывать всегда про анализ проектного решения и правильную ли Вы проблему вообще решаете.
    Ответ написан
    2 комментария
  • В чем разница между delete и nullptr?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    g = nullptr не удалаят память, оно просто записывает в переменную g значение со смыслом - "указатель вникуда". Память при этом остается нетронутой и к ней можно обращаться, что вы и делаете, запомнив указатель в другой переменной.

    delete[] же освобождает память, а значит, все последующие обращения к ней, что при помощи g, что при помощи gg - будут вызывать UB
    Ответ написан
    Комментировать
  • Как правильно выделить память (с проверкой выделения) для массива класса?

    @res2001
    Developer, ex-admin
    какой из вариантов наиболее эффективен / наиболее используемый

    Создание класса в динамической памяти делится на 2 этапа:
    1. выделение "сырой" памяти у менеджера памяти
    2. инициализация памяти - вызов конструктора класса на выделенном участке памяти.
    Вариант с malloc не выполняет вторую часть. Для того что бы закончить процесс в этом варианте вам надо использовать размещающий new, передав указатель на ранее выделенную память. Деструкторы так же нужно будет вызывать явно.

    Если вариант с malloc довести до логического конца, то он будет делать то же самое что и вариант с new, никаких преимуществ тут нет. Но не забываем про явный вызов деструктора.

    При удалении класса из динамической памяти присутствуют обратные этапы: вызов деструктора и освобождение памяти.

    malloc обычно используют в плюсовом коде, когда реализуют собственные аллокаторы и нужен "сырой" не инициализированный блок памяти. Но и в этом случае вполне можно обойтись без malloc - использовать new char[MEM_SIZE]
    Ответ написан
    Комментировать
  • Как найти точки пересечения 2х фигур с++?

    Adamos
    @Adamos
    Я не могу найти точки пересечения прямоугольника и окружности

    Беда. Может, поискать - в поисковике?
    Ответ написан
    3 комментария
  • Как правильно выделять сырую память для размещения в ней объектов?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Нет, если вы не вызвали конструктор и обратились к объекту, вы схлопочете UB, формально говоря.
    Да и какой смысл в том, чтобы навыделять памяти, а конструкторы не вызывать? Это нарушает принцип RAII как минимум.
    Кстати, именно статической памяти я в вашем коде не увидел.

    Так что со стороны это все выглядит как проблема X-Y.
    Ответ написан
    8 комментариев
  • В разных IDE код выдаёт разный ответ, как так?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Оператор << не является точкой следования, таким образом, вы получаете неопределенное поведение - у вас вызовы ++(*val) не отделены точкой следования друг от друга.

    Вот так ошибки не будет:

    cout << a.get();
    cout << b.get();


    Потому что ; является точкой следования.

    В более свежих версиях стандарта может быть другая терминология, но суть проблемы - прежняя.
    Ответ написан
    Комментировать
  • Почему не находится определение при линковке объектников ассемблера и c++?

    @galaxy
    Попробуйте extern "C" int _sub(int, int);
    Ответ написан
    Комментировать
  • Как организовать работу одного радиопередатчка и нескольких приемников?

    gbg
    @gbg Куратор тега Электроника
    Любые ответы на любые вопросы
    В условиях небольшого помещения сеть из ESP8266 на вайфае - первый выбор, оставляющий далеко позади блютус (маленький радиус стабильной работы) и уж тем более радиомодули на безлицензионных диапазонах (на автора этой идеи я бы хотел так сказать, посмотреть - с легкой руки усложнить задачу на два порядка - это надо уметь!)

    Также не нужны разного рода ModBus over TCP - потому что это лишний слой абстракции поверх уже имеющейся в IP адресации.

    Фактически, вам нужно просто слушать сокет, выполнять команды и отвечать на пинги.
    Ответ написан
    Комментировать
  • Почему 0.2f + 0.3f == 0.5f?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    0.2 = 1.100110011001100110011012 * 2-3
    0.3 = 1.001100110011001100110102 * 2-2
    Приводим к старшей степени, сохраняя количество двоичных разрядов.
    0.2 = 0.110011001100110011001102 * 2-2
    Складываем, получаем
    0.110011001100110011001102 * 2-2
    +
    1.001100110011001100110102 * 2-2
    =
    10.00000000000000000000002 * 2-2
    = 1.0000000000000000000002 * 2-1 = 0.5
    Ответ написан
    Комментировать
  • Как получить id потока в процессе C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно получить список всех потоков одного процесса через Thread32First/Thread32Next (пример).

    Ищется в гугле буквально по "winapi list threads".
    Ответ написан
    Комментировать
  • Почему std::endl не требует круглых скобок?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Да, это реально так. Более того, при желании, можно написать свое такое же - например, как в моем миниатюрном классе логов:
    Lout& operator << (Lout& out, Lout& (*func)(Lout&));
    Lout& operator << (Lout& out, std::function<Lout& (Lout&)>&&func);
    
    //stream commands & modifiers
    Lout &anounce(Lout &ret);
    Lout &flush(Lout& out);
    Lout &ok(Lout& out);
    Lout &fail(Lout& out);
    Lout &newLine(Lout& out);
    Lout &pop(Lout& out);
    Lout &Color(Lout& out, const uint8_t);
    Lout &noColor(Lout& out);
    Ответ написан
    Комментировать
  • Существует ли такой анализатор кода?

    Viktor_T2
    @Viktor_T2
    python developer
    Комментировать
  • Почему не воспроизводится звук?

    @rPman
    Потому что эта функция не умеет играть .mp3 файлы, только waveform audio, при наличии соответствующего драйвера, поддерживаются кодеки (например ac3 или даже mp3, по крайней мере я смутно помню свои эксперименты с этим еще в winxp), но формат файла должен быть все равно riff (т.е. wav или avi, кстати последний под вопросом, сможет ли он выцепить от туда звуковую дорожку, хз)
    https://docs.microsoft.com/en-us/previous-versions...
    The sound specified by pszSound must fit into available physical memory and be playable by an installed waveform-audio device driver.
    Ответ написан
    Комментировать
  • Лагает фотошоп, премьер про на мощном пк, как убрать лаги?

    sugarraisin
    @sugarraisin Автор вопроса
    И так, пораскинув мозгами, понял, что такое началось, после покупки материнской платы AsRock PRO4 z390.
    Пошерстив сайты, форумы, много советов было про отключение "энергосбережения в биос". Это в разделе «Расширенное», дальше в конфигурации ЦП, там типо как-то с буквой «С» все режимы выключите. Отключил то, что нашел и знаете, ощущается работа системы бодрее, но все еще не идеально. Уверен, еще пару пунктов в биосе этой материнки я не отключил. Но улучшения заметны, серьезно. Безумно благодарен каждому, кто уделил время ответив в этой теме ( или топике ), с попыткой помочь мне, безумно приятно, что хороших людей еще много. Так же, буду благодарен, если подскажете, как окончательно отключить эти "кастрационные" фишки
    Ответ написан
    Комментировать
  • Как можно использовать union в качестве ключа unordered_map?

    includedlibrary
    @includedlibrary
    Вам нужно использовать структуру из двух значений типа short. Для неё уже нужно будет определить вычисления хэш-функции, например так:
    struct MyStruct {
        unsigned short x;
        unsigned short y;
    };
    
    template<>
    struct std::hash<MyStruct> {
        std::size_t operator()(MyStruct const& s) const noexcept {
            return ((size_t)s.x << 16) | s.y;
        }
    };
    Ответ написан
    4 комментария
  • Есть ли разница для шифрования UTF-8 строк и ASCII строк через SHA-1?

    Adamos
    @Adamos
    В UTF-8, UTF-16LE и UTF-16BE символ кириллицы занимает два байта.
    Но в каждом из этих случаев это будут два РАЗНЫЕ байта.
    Соответственно, алгоритм, работающий с байтами, выдаст РАЗНЫЙ хэш.
    Вам, если вы не хотите разложить себе на дороге грабель, лучше приводить свою информацию к байтам самостоятельно, а не полагаться на какие бы то ни было "волшебные" библиотеки.
    Ответ написан
    2 комментария
  • Как правильно построить многоугольник по точкам?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Картинка не видна, но по коментариям понятно, что вам хочется получать только выпуклые многоугольники?

    Проверить, что что-то не так можно через векторное произведение последовательных сторон.

    Для всех 3 подряд идущих вершин a, b и c, то надо проверить, что (b-a)*(c-b) всегда дает одинаковый знак (или всегда <=0 или всегда >=0). Это векторное произведение.
    Формула в вашем случае будет (xb-xa)*(yc-yb)-(xc-xb)*(yb-ya).

    Еще можно построить выпуклую оболочку (convex hull).
    Вот расписан алгоритм, как ее построить по заданным точкам: https://e-maxx.ru/algo/convex_hull_graham

    Edit: Еще можно, вместо сортировки точек в выпуклую оболочку, игнорировать клики от пользователя, которые делают текущий многоугольник невыпуклым. Опять же, проверку невыпуколсти можно делать только для новых сторон: В последней, новой и первой точках.
    Ответ написан
    2 комментария
  • Почему побайтовый сдвиг даёт разные результаты?

    @res2001
    Developer, ex-admin
    Читайте тут до прояснения раздел "Bitwise shift operator.
    Смысл в том, что если вы знаковое число сдвинули влево так, что старшим разрядом стала 1, то в результате получится отрицательное число. При сдвиге вправо знакового числа, освобождающиеся слева разряды заполняются битом знака (а не нулем), поэтому результат сдвига отрицательного числа так же будет отрицательным (а положительного - положительным:). Если сдвигать вправо беззнаковое число, то свободные биты будут всегда заполнятся нулями.
    Кстати, на сколько помню, по стандарту знаковость char не определена (может быть как знаковым так и беззнаковым). Вам с вашим примером не повезло, char оказался знаковым. Зато это дало возможность немного глубже понять сдвиги.
    Ответ написан
    6 комментариев