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

    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 комментариев
  • Как настроить сборку для линковки двух разных версий одной библиотеки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Автоматический метод могу предложить только один: перезагрузите компьютер. Если не помогло, то придется искать ошибку в коде.
    Ответ написан
    8 комментариев