Задать вопрос
  • Данные в таком случае будут хранится в стеке?

    @Mercury13
    Программист на «си с крестами» и не только
    Не пиши так, пожалуйста.
    Перед нами продление жизни временного объекта.
    Когда ссылка исчезнет — а она исчезнет после точки с запятой — указатель будет смотреть в никуда, и только от Ктулху зависит, когда переменную перезапишут.
    Правильно так:
    const int& ref = 1;
    const int* Number = &ref;

    Данные могут лежать где угодно — теоретически на стеке, но оптимизатор может перекинуть их и в сегмент данных.

    В общем, правило. Продлённый объект живёт, пока живёт та ссылка, что его продлила. Ссылки и указатели, что сделаны уже из этой ссылки, не в счёт: Си++ всё-таки не «мусорный» язык. Временный объект живёт до точки с запятой, за исключением нескольких случаев: явная команда придержать объект (о которой у нас и речь), создание/копирование массива (для простоты компиляции и чтобы не раздувать стек), с Си++23 в команде «цикл по объекту» ради безопасности и предсказуемости.
    Ответ написан
    Комментировать
  • Как правильно перегрузить шаблонный оператор (метод, функцию), чтобы наследники попадали в нужный?

    @Mercury13
    Программист на «си с крестами» и не только
    Итак, перед нами конфликт первой и второй функции, и надо первую как-то ограничить.

    Вариант 1. Концепция Си++20.
    template <class T>
    concept Printable = requires(T x) {
            std::cout << x;
    };
    
    struct Class {
        template<Printable Text>
        Class& operator<<(const Text& text) {
            cout << text << endl;
            return *this;
        }


    Вариант 2. Обратная концепция.
    template<uint8_t i>
    struct Id {
        constexpr static uint8_t id = i;
        using SpecialPrint = void;
        // какие-то элементы класса с методами
    };
    . . . . .
    template <class T>
    concept SpecialPrintable = requires {
        typename T::SpecialPrint;
    };
    
    struct Class {
        template<class Text>
        Class& operator<<(const Text& text) {
            cout << text << endl;
            return *this;
        }
        
        template <SpecialPrintable Special>
        Class& operator<<(const Special& text) {
            specialPrint(text);        
            return *this;
        }
        
        template<uint8_t i>
        void specialPrint(const Id<i>& text) {
            cout << (int)i << endl;
        }
    };


    А на 17 без концепций…
    template<uint8_t i>
    struct Id {
        constexpr static uint8_t id = i;
        using SpecialPrint = void;
        // какие-то элементы класса с методами
    };
    . . . . .
    
    template<class T, class Dummy = void>
    struct IsSpecPrintable { static constexpr bool value = false; };
    
    template<class T>
    struct IsSpecPrintable<T, typename T::SpecialPrint> { static constexpr bool value = true; };
    
    struct Class {
        template <class T>
        Class& operator<<(const T& text)
        {
            if constexpr (IsSpecPrintable<T>::value) {
                specialPrint(text);
            } else {
                normalPrint(text);
            }
            return *this;
        }
    
        template<class Text>
        void normalPrint(const Text& text) {
            cout << text << endl;
        }
    
        template<uint8_t i>
        void specialPrint(const Id<i>& text) {
            cout << (int)i << endl;
        }
    };
    Ответ написан
    1 комментарий
  • Можно практический пример где можно использовать очередь на двух стеках?

    @Mercury13
    Программист на «си с крестами» и не только
    В разных необычных структурах данных.
    https://habr.com/ru/articles/483944/
    Вот очередь, поддерживающая за амортизированное O(1) необратимую ассоциативную операцию (например, минимум).
    А это, в свою очередь, позволяет за O(N) эту самую необратимую ассоциативную операцию вычислить в окнах по 10 (или по 20, или по 100).
    Ответ написан
    Комментировать
  • Как работает массив?

    @Mercury13
    Программист на «си с крестами» и не только
    Массив — это отдельный тип, но он конвертируется в указатель. Мало того, в Си передача массивов в функции возможна только через указатель.
    Потому *array — это превратить в указатель, разыменовать, и будет ССЫЛКА на 0-й элемент.
    array+1 — это конвертируем в указатель, сдвигаем на единичку
    А *(array+1) — ссылка на 1-й элемент.
    Ответ написан
    Комментировать
  • Почему не запускается программа на Qt?

    @Mercury13
    Программист на «си с крестами» и не только
    Похоже на некорректные DLL. И, по-моему, виноваты DLL Си++ — обычно это творится, если используют сторонний компилятор (свежий Си++ дорогого стоит), а библиотеки из Qt.
    Ответ написан
  • Как максимально эффективно по скорости написать этот алгоритм преобразования строки?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Каким-то образом преобразовать обе строки, чтобы избавиться от расхождений по стартовым слэшам. Слишком мало информации, КАК это сделать — возможна ситуация, когда вторая строка не начинается со слэша, а первая нет, но бывают ли другие?
    2. Убедиться, что вторая строка — префикс первой. Если нет — непонятно, что делать.
    3. Если вторая строка непуста и не кончается слэшом, убедиться, что в первой на этом месте слэш. Пропустить его.
    4.1. Если от первой строки ничего не осталось — если в конце слэш, пропустить, и извлечь кусок до следующего с конца слэша.
    4.2. А если осталось — извлечь кусок до слэша.
    5. Придумай методику хранения информации. Вероятно, выделить память? — тогда на каждый результат придётся давать free.
    Ответ написан
    Комментировать
  • Как сделать кэш динамики запасов?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Пока вижу такой способ закэшировать динамику запасов. Вместе с каждым событием держим двойной кэш.
    1. Товары по очереди (0, 1, 2, 0, 1, 2…)
    2. Тот товар, который задействован в событии.

    Тогда, прочитав m старых событий, можно восстановить полный запас всего на любой момент.
    Ответ написан
    Комментировать
  • Как в Qt Widgets сделать, чтобы серый QToolButton по-другому реагировал?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Опять самому отвечать.
    Всё очень просто: наладить installEventFilter / eventFilter, скажем, на QEvent::MouseButtonPress. Он работает даже сквозь засеренные компоненты.
    Ответ написан
    Комментировать
  • Почему parentWidget возвращает nullptr?

    @Mercury13
    Программист на «си с крестами» и не только
    Простите, что пишу с опозданием.
    Потому что в Qt есть два «родителя».
    Родитель, отвечающий за уничтожение, и родитель в иерархии окон.
    Это вы объявили, кто автоматически уничтожит окно. А тут ещё надо someParent->addWidget(someChild);.

    В Delphi это названо owner и parent соответственно.
    Ответ написан
    Комментировать
  • Нормально ли создавать пустую вирутуальную функцию?

    @Mercury13
    Программист на «си с крестами» и не только
    ВСЕ ПРИМЕРЫ ЖИВЫЕ, у меня перед глазами.
    • stream.flush — физический сброс данных на устройство (при выводе) или сброс буферов (при вводе) имеет место только с реальным устройством, а написанные прикладным прогером потоки редко с ними работают, потому пустая.
    • Импортёр из системы управления предприятием, который для каждого, например, рецепта производства вызывает callback. Если рецепты не поддерживаются — ничего не делать.
    • В каком-то виджете Qt напрочь убираем реакцию на колесо мыши.
    • Программа использует для ускорения кучу кэшей, которые перед импортом данных выкидываются. Если выкидывать нечего — функция compactMemory пуста.
    • Или твоя фигура-квадрат, для которой поворот ничего не делает.
    Ответ написан
    Комментировать
  • Как установить плагин в notepad++?

    @Mercury13
    Программист на «си с крестами» и не только
    Отметь галку, кнопка перестанет быть серой.
    Ответ написан
    1 комментарий
  • Алгоритмы и структуры данных?

    @Mercury13
    Программист на «си с крестами» и не только
    Если f(n) ≡ 0 (неотрицальна → асимптотически неотрицательна), то вполне срабатывает, что 0=Θ(0).
    То есть по нашему определению множества Θ, если оно непустое, то g обязана быть асимптотически неотрицательной — но не обязательно асимптотически положительной.
    Ответ написан
  • Лучше ли использовать enum для цвета нежели struct?

    @Mercury13
    Программист на «си с крестами» и не только
    Разрешите вмешаться. Штатное процессорное выравнивание — 8 на x64.

    Выравнивания ниже штатного иногда увеличивают, чтобы одним махом обрабатывать несколько полей. Например, для умножения цветов в формате RGB на x86 кто-то одним махом множил R и B, а вторым — G. Но при этом для производительности цвет должен иметь выравнивание 4.

    Выравнивания выше используют только для хитрых системных целей: выйти за строку кэша, работать с железом, которому такое выравнивание нужно, иногда для оптимизации: улучшенный Doom грузил таблицы преобразования цветов по адресам, кратным 64K, и собственно в EDX грузил адрес, в DH цвет фона, в DL цвет изображения — и получал в EDX указатель на новый цвет.

    Касательно SDL — они в этой функции хотели абстрагироваться от формата цвета (RGB или BGR).

    С enum — всё больше зависит от архитектуры проги: например, вы можете абстрагироваться от реальных значений цветов и иметь цвета «фон», «передний план», «рамка таблицы», «хороший», «плохой». Разница в производительности невелика.
    Ответ написан
    Комментировать
  • Зачем использовать кучу если есть стек? а так же где применяются указатели и ссылки?

    @Mercury13
    Программист на «си с крестами» и не только
    Да, работа с сегментом данных и стеком значительно легче для процессора, и потому их используют везде, где можно. Куча используется в четырёх основных сценариях.
    1. Выделение большого количества данных, которые стек вместить не может. Пример: матрица на много-много мегабайт.
    2. Выделение не известного заранее количества данных. Обычно «не известное заранее» = «возможно, большое», но и тут есть интересный пример: даже если 1000 символов на строки нам хватает за глаза, строки используются настолько часто, что слишком уж расточительно на каждую строку пускать по килобайту.
    3. Сложное время жизни объекта, не ограниченное рамками функции. Примеры могут быть в играх: функцией Spawn объект появляется, функцией Kill уничтожаем.
    4. Использование виртуального полиморфизма (см. ООП). Игровые позиции, как ни странно, плохо совместимы с ООП, так что давайте будет так: функция CreateStream может создать поток, работающий с отрезком памяти или файлом.

    Указатель может иметь такие значения.
    • Единственная «ниточка», ведущая к объекту в куче. Все указатели перенаправили, а объект не уничтожили — всё, кусочек памяти «висит».
    • Некие «стрелочки», налаженные между объектами, чтобы устроить связный список, дерево или что-то ещё. Независимо от того, какие объекты: мы вполне можем в небольшой игре создать кучу объектов с запасом, скажем, в сегменте данных или даже стеке, и налаживать между ними такое же взаимодействие, как будто они в куче.
    • Просто «стрелочка» на кусок памяти, которую принимает или отдаёт функция. Причём эта стрелочка может указывать и в пустоту (nullptr). Всё, что функция изменяет по этой стрелочке, будет видеть и вызывающая программа — в отличие от передачи по значению. Или просто объект такой большой, что его копировать бессмысленно. Или архитектурно некопируемый (системный ресурс вроде открытого файла).
    • Арифметика указателей позволяет работать с кучей объектов, которые сидят рядом в памяти. В Си++ есть понятие «итератор» — объект, похожий на указатель и обладающий арифметикой указателей, но позволяющий пробежаться, например, по дереву поиска.
    • Опять-таки, виртуальный полиморфизм приводит к тому, что к нам приходит не-знамо-что не-знамо-какого устройства (мы лишь знаем, что этот объект, скажем, умеет читать данные как из файла) — обращаться к таким объектам можно только через указатели. В отличие от предыдущего примера с итераторами, мы не понимаем даже самых основ объекта — сколько он байтов занимает, как его создавать, копировать и уничтожать (часто в интерфейс объекта входят столь же виртуальные команды «сделать копию» и «уничтожить», но это отдельный вопрос).

    На ссылку смотрите как на указатель, который 1) не может указывать в пустоту; 2) надо обязательно сразу же присвоить и дальше не перенаправлять. Самое то, когда функция принимает или отдаёт «стрелочку» на кусок памяти, и стрелочка никогда не может указывать в пустоту.
    Ответ написан
    Комментировать
  • Как сделать отклонение для вектора?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Умножим наш point на r.
    2. Повернём (rx, ry, 1) так, чтобы (0,0,1) → d. Ищите эту матрицу где-то в движке: вы имитируете разброс оружия — так что это будет матрица поворотов камеры. Если прицел не в центре экрана (бывает для всяких там гранатомётов) — применяем ту же самую поправку. Если видовая матрица и матрица наводки развязаны (бывает в сетевой игре) — то брать матрицу наводки, понятно.
    3. Снова нормализуем.
    Ответ написан
    Комментировать
  • Совместимость Dvi?

    @Mercury13
    Программист на «си с крестами» и не только
    Должно — если, конечно, Type-C даёт HDMI-видеовыход. Глючья в этом плане столько, что переходник HDMI→VGA, например, на одном мониторе работает и на другом нет. Но это именно глючьё непредсказуемое.

    DVI+, как я его называю — потому что на цифровом DVI виден минус и на полном плюс — может, сделан, потому что попался такой разъём, и аналоговые штыри никуда не подключены. Ниже вероятность, что и VGA тоже поддерживается.
    Ответ написан
    Комментировать
  • Как подключить файл во время работы программы?

    @Mercury13
    Программист на «си с крестами» и не только
    Что значит «подключить файл»?
    Загрузить файл данных? std::ifstream.
    Загрузить динамическую библиотеку? Ищи системные функции вроде LoadLibrary в Windows и dlopen в Linux. (Кроссплатформенных библиотек загрузки DLL/SO мало, а стандарт за этим даже не гонялся.) Но в любом случае потребуются заголовки функций в препроцессорном файле.

    Си++ компилирует в машинный код и не таскает за собой компилятор, и потому динамически подключить файл исходника, как это делает какой-нибудь PHP, не может. Только динамическую библиотеку — какие-то исходники, скомпилированные в машинный код.

    Файл исходника подключается не препроцессором, а системой сборки (потому что так работал ассемблер, и потому что разделение компилятора, линкера и системы сборки позволяет соединять вместе код, написанный на разных языках, и потому что хорошая система сборки позволяет включать в сборку нестандартные шаги). Да, существует устройство кода «одна единица трансляции» — у неё кратчайшее время полной перекомпиляции, но невозможна компиляция по частям и на многих процессорах, и одну единицу обычно берут для среднего размера библиотек (SqLite), где-то до минуты — время немалое, но любая значимая программа перебьёт, и один хрен библиотеку пересобирают только целиком. Препроцессором обычно подключаются заголовки типов и функций.

    Если нужна поддержка скриптов в проге — смотри на Lua. В последнее время очень любят Python. но я не в курсе и один хрен пригодно только для больших прог, готовых таскать с собой дистрибутив Питона.
    Ответ написан
  • Какая сложность у std::sort?

    @Mercury13
    Программист на «си с крестами» и не только
    Символ Ландау g(x) = O(f(x)) при x→y означает: g(x)⩽kf(x) при x, достаточно близких к y. В данном случае y=∞.
    То есть с точностью до константы. А как Wataru сказал, основание логарифма — это умножить на константу.

    А я попытаюсь сказать, почему удобны символы Ландау.
    1. Математическим исследованием сложно выяснить, сколько операций займёт одна итерация цикла — две или тысячу. Этим пусть занимаются микрооптимизации.
    2. Зато в любую программу загонят столько данных, что она сломается. И как правило — если не доказано обратное — асимптотическая сложность быстро пересилит эту самую константу, и программа большей сложности сломается первой.
    3. Ну вот прога сломалась, и мы занялись микрооптимизациями и заменили процессор, и получилось, скажем, вдвое — насколько более крупные задачи мы теперь можем решать? Если O(N), то вдвое более крупные. Если O(N log N), то несколько меньшие, чем вдвое. А если O(N²), то в 1,4 раза.
    Ответ написан
  • Можно ли в ИБП смягчить стартовые токи умным резистором типа «лампочка»?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Сработало. Даже проверил, что будет, если держать лампочку включённой — лампа ярко горит, БП уходит в защиту.
    Ответ написан
  • Почему нижняя часть дисплея MacBook дублируется верхней частью дисплея?

    @Mercury13
    Программист на «си с крестами» и не только
    Видяха, шлейф, дешифратор матрицы. Больше похоже на последний.
    Какое разрешение вашего ноутбука? — это важно, дешифратор заглючивает где-то близко к степеням двойки.
    Ответ написан
    7 комментариев