Задать вопрос
  • Ошибка D8021 недопустимый числовой аргумент "/Wno-error=invalid-offsetof" откуда может появиться данная проблема и как решить?

    @Ariox41
    Строка
    set(CMAKE_PREFIX_PATH "C:\\Qt\\6.1.3\\mingw81_64\\lib\\cmake")

    намекает, что вы пытаетесь подключить бинарники, скомпилированные при помощи mingw, к проекту, собираемому при помощи msvc. Это в любом случае не сработает, ABI несовместимы.

    В данном случае это также может быть причиной ошибки, т.к. вы подключаете файлы конфигурации cmake, которые содержат флаги компилятора, которые при сборке были прописаны как публичная зависимость. Флаги от mingw, естественно, недопустимы для msvc.

    Проще говоря, либо установите версию Qt, соответствующую вашему компилятору, либо установите msys2, и используйте mingw + Qt из пакетов (но для mingw нет QWebEngine).
    Ответ написан
  • Почему NetBeans 8.2 подчеркивает все красным?

    @Ariox41
    Скорее всего он не нашел стандартную библиотеку. Какие ОС и компилятор?
    Ответ написан
  • Как выйти из нескольких вложенных циклов?

    @Ariox41
    Простейший способ для c++ - обернуть в лямбду и выйти через return. Аналогичный подход можно применять для инициализации переменных, но о читаемости такого кода до сих пор идут споры.

    LIMIT = ...
    matrix = ...
    count = ...
    [&]{
        for (int i = 0; i < LIMIT; i++) {
            for (int j = 0; j < LIMIT; j++){
                int value = matrix[i][j];
    
                for (int a = 0; a < LIMIT; a++) {
                    for (int b = 0; b < LIMIT; b++)  {
                        if (value == matrix[a][b]){
                            count++;
                        }
                        if (count == 2) {
                            std::cout << "Indexes of elements: " << "[" << i << ", " << j << "], ";
                            std::cout << "[" << a << ", " << b << "]" << std::endl;
    
                            return;
                        }
                    }
                }
            count = 0;
            }
        }
    }();
    Ответ написан
    Комментировать
  • Причины утечек памяии?

    @Ariox41
    В деструкторе CGamePetri ошибка:

    for( vector<CPetriAction *> :: iterator i = m_Messages.begin(); i != m_Messages.end();  )
    {
         delete *i;
         m_Messages.erase( i );
    }


    Когда вызывается erase итератор становится невалидным. На практие скорее всего удаляются элементы 0, 2, 4 ... в первой половине вектора, т.к. когда удаляется нулевой элемент - первый становится нулевым, второй первым, и итератор переходит на новый первый элемент, который раньше был вторым. Решается легко:
    for( vector<CPetriAction *> :: iterator i = m_Messages.begin(); i != m_Messages.end();  )
    {
         delete *i;
    }
    //m_Messages.clear(); // - в данном случае смысла нет, т.к. это деструктор


    Или еще проще:
    for(auto& ptr:  m_Messages){
       delete ptr;
    }


    Если в m_Messages хранить unique_ptr - тогда и этого не нужно, объекты удалятся автоматически в деструкторе вектора.
    Ответ написан
  • В чем причина ошибки компилятора "use of deleted function" в данном коде?

    @Ariox41
    Просто замените круглые скобки на фигурные в списке инициализации: пример.

    Пустой список аргументов не может быть передан в конструктор через круглые скобки - иначе это будет эквивалентно строке MyClass value(); - а это уже объявление функции. Из-за этого пустой список аргументов интерпретироваться как пустой список инициализации, но пустой список инициализации опять же нельзя передать в конструктор без аргументов, используя круглые скобки, т.к. один аргумент всё-таки есть. Но при использовании фигурных скобок список инициализации нормально вызывает конструктор без аргументов. При этом неявное преобразование из пустого списка инициализации в MyClass возможно - неявно вызывается конструктор без аргументов:
    void foo(MyType2&&){ }
    foo({}); // Компилируется

    А значит строка MyClass({}) преобразует {} во временный объектMyClass, а его попытается передать в удалённый конструктор перемещения MyClass
    Ответ написан
    Комментировать
  • Как проверить вывод на число?

    @Ariox41
    Вывод - это вывод из программы в поток (cout), ввод - это ввод из потока в программу (cin), это можно понять по названиям.

    Один из вариантов - считывать не чисто, а строку, а затем уже преобразовать строку в чисто другими функциями.
    Или можно воспользоваться интерфейсом обработки ошибок потоков:

    #include <iostream>
    #include <limits>
    
    int main() {
        int num = 0;
    
        while(num != -1) {
            std::cout << "Enter the number to push: ";
            std::cin >> num;
            if(std::cin.fail()){
                std::cout  << "It is not number" << std::endl;
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<int>::max(), '\n');
            } else{
                std::cout << "num = " << num << std::endl;
            }
        }
        
        return 0;
    }
    Ответ написан
    Комментировать
  • Как правильно передать двумерный массив в функцию?

    @Ariox41
    Можно так:

    #include <array>
    
    template<std::size_t ColumnCount, std::size_t RowCount > 
    int foo(int (&matrix)[ColumnCount][RowCount]){ 
       int r = 0;
       for(auto& row: matrix){
           for(auto& x: row)
              r += x;
       }
       return r;
    }
    
    int bar(){
        int matrix [][2] = {{1, 2}, {3, 4}, {4, 6}};
        return foo(matrix);
    }


    С-массивы в функции можно передавать только по ссылке. Или преобразовать в массив указателей.

    Вообще, для передачи С-массивов придуман std::array, но двумерный C-массив нельзя напрямую привести к std::array<std::array<int, M>, N>. Но можно изначально работать с std::array:
    template<std::size_t ColumnCount, std::size_t RowCount > 
    
    int foo(std::array<std::array<int, RowCount>, ColumnCount>& matrix){ 
       int r = 0;
       for(auto& row: matrix){
           for(auto& x: row)
              r += x;
       }
       return r;
    }
    
    int bar(){
        std::array<std::array<int, 2>, 3> matrix = {{{1, 2}, {3, 4}, {4, 6}}};
        return foo(matrix);
    }
    Ответ написан
  • Как учить C++ программисту который не учился в вузе в данной сфере?

    @Ariox41
    По стандартной библиотеке могу посоветовать "Стандартная библиотека C++. Справочное руководство". Я, правда, читал только первое издание (сейчас актуально второе), но вряд ли она стала сильно хуже. Ну и cppreference.com для изучения стандартной библиотеки тоже полезен.

    По многопоточности однозначно стоит почитать "Параллельное программирование на С++ в действии. Практика разработки многопоточных программ" - язык там может и не самый простой, но там хорошо описаны как библиотека поддержки потоков, так и основы модели памяти (в связи с атомарными переменными).

    По остальным запросам сложнее - всё сильно зависит от текущего уровня знаний и от цели изучения. Возможно, стоит начать с книг для новичков, где объясняются основы языка (тут много вопросов про такие книги). Но наверняка большая часть изложенной в них информации вам уже знакома, при этом часто в таких книгах приводятся не лучшие способы решения задач. Шлее неплохой выбор для новичка в C++, знакомого с другими ЯП, но он всё же больше о C++ в экосистеме Qt, с точки зрения чистого C++ там хватает недостатков.

    Можно попробовать почитать Майерса ("Эффективное использование C++. 50 рекомендаций..." и/или "35 рекомендаций", не стоит начинать с последних книг). Они могут оказаться слишком сложными, но отвечают на большую часть ваших запросов (или хотя бы станет понятно, куда копать дальше и нужно ли оно вам). Там некоторые вещи однозначно будут непонятны, но при первом прочтении их можно просто пропустить - главы слабо связаны между собой. Меня в своё время книги Майерса мотивировали изучать C++ всерьёз (до этого выбирал между C++ и Java), на тот момент я знал C++ на уровне C с классами.
    Ответ написан
    4 комментария
  • Какой учебник выбрать новичку для изучения C++?

    @Ariox41
    Майерса стоит почитать однозначно, но позже, и начать лучше с "55 советов" или "35 советов" - там лучше объясняются идеи modern c++ (но старые издания я бы не стал покупать, тем более что отдельные главы из них и так растащены по множеству статей в интернете). Эти книги предназначены не для новичков, скорее они предназначены для тех, кто уверенно пишет хотя бы в стиле "C с классами" и имеет хотя бы общее представление о шаблонах. В них объясняются подходы, позволяющие улучшить читаемость кода и уменьшить дублирование.

    Книги для новичков я не читал, посоветовать не могу.
    Ответ написан
    Комментировать
  • Как правильно использовать QWidget в QML?

    @Ariox41
    В строке w = new QPushButton; не указан родитель, а значит кнопка создаётся для цикла событий основного потока. Однако QML может работать в своём собственном потоке (с которым связан свой цикл событий), из-за чего кнопка создаётся в потоке QML, но для цикла событий основного потока. Об этом и написано в сообщении об ошибке. Должна помочь передача родителя, работающего в потоке QML: w = new QPushButton(this);. При этом кнопка будет использовать цикл событий родителя (this уже от своего родителя знает, в каком он потоке).
    Ответ написан
  • Rust использует виртуальную машину?

    @Ariox41
    Rust - это язык программирования, виртуальная машина - это среда выполнения. Вы можете скомпилировать Rust в wasm и запускать под виртуальной машиной (node.js или в браузере), или можете скомпилировать в машинный код и запускать как как обычное приложение. Правда, пока что экосистема wasm еще не развита, но в целом работает, да и сам язык до зрелости еще не дотягивает.

    Отличие от языков, изначально рассчитанных на виртуальную машину, заключается в том, что сам Rust не содержит предположений по этому по этому поводу и не предоставляет дополнительных функций, основанных на возможностях виртуальной машины. В частности, в нём нет возможности управлять jit-компиляцией. Впрочем, всё то же самое можно сказать и про C++, но там исторически сложилось, что долгое время под него просто не было виртуальной машины (сейчас его тоже можно скомпилировать в wasm или в JavaScript).

    На практике Rust компилируется в LLVM - байт код, с которым можно делать что угодно - компилировать в машинный код, запускать напрямую на виртуальной машине (теоретически) или транслировать куда-то еще.
    Ответ написан
    Комментировать
  • Unittests в Qt, как правильно организовать структуру проекта?

    @Ariox41
    Каждый набор тестов в QTest обычно создается как отдельный подпроект (приложение). Соответственно, и запускаются тесты как отдельное приложения. Выбор текущего активного проекта для запуска в QtCreator осуществляется через панель "проекты" слева, или по "ctrl + T", это относится и к тестам. В принципе, тесты можно сосредоточить и в одном проекте, но это крайне неудобно как раз из-за проблемы, с которой вы столкнулись. Для такой конфигурации лучше подходит Catch. QtCreator вроде бы умеет запускать все тесты одновременно, но я этим не пользовался.
    Ответ написан
    Комментировать
  • Корректен ли этот код?

    @Ariox41
    В стандарте есть правило, по которому при создании константной ссылки на автоматически управляемый объект его время жизни расширяется до времени жизни константной ссылки. Однако это не относится к оператору return и есть особое правило для списков инициализации (подробнее тут). Соответственно, в следующем примере функция getRef некорректна, но функция foo реализована корректно.
    const std::string &getRef() {
        std::string tmpObject = "123";
        return tmpObject;
    }
    
    void foo(){
        const std::string& ref = getRef();
        std::cout << ref; // Выведет 123
    }


    В любом случае, использование такого подхода не имеет смысла - можно просто полагаться на оптимизацию возвращаемого значения и писать так:

    std::string getStr() {
        std::string tmpObject = "123";
        return tmpObject;
    }
    
    void foo(){
        std::string str = getStr();
        std::cout << str; // Выведет 123
    }
    
    // На крайний случай можно так - это точно корректно, но лучше не нужно - иначе кто-нибудь 
    // может случайно удалить const, что приведёт к проблемам. 
    void bar(){
        const std::string& ref = getStr();
        std::cout << ref; // Выведет 123
    }
    Ответ написан
    3 комментария
  • Java или C++ в качестве первого языка. Что выбрать?

    @Ariox41
    Возможно, хорошим вариантом будет Rust . Это молодой язык, и не факт, что он пригодится вам в ближайшие пару лет, но для обучения у него есть несколько преимуществ:
    • С одной стороны, он предсказуем, как и C++, т.е. обычно достаточно очевидно, как будет выполняться тот или иной кусок кода на низком уровне. С другой, он достаточно прост (ненамного сложнее JAVA) и автоматизирует управление ресурсами (без сборщика мусора, но так даже лучше).
    • Как и в C++, можно использовать абстракции с нулевой стоимостью (чего в Java нет в принципе), и для этого не требуется сложный шаблонный код.
    • Компилятор обругает вас за допущенные ошибки. Если не обругает компилятор - в большинстве случаев будет ошибка времени выполнения. C++ тоже часто находит ошибки во время компиляции, но в Rust это реализовано лучше, при этом на C++ сложнее искать ошибки времени выполнения. В JAVA ошибки по большей части возникают во время выполнения, что не очень хорошо для обучения - многие ошибки на простых примерах просто не возникают.
    • Модель управления ресурсами изначально учитывает многопоточность, что снижает вероятность возникновения ошибок в многопоточных программах.
    • Есть стандартный менеджер пакетов и система сборки, чего сильно не хватает C++. У Java тоже есть неплохие менеджеры пакетов, но их несколько, пусть и совместимых, что иногда осложняет жизнь.
    • У него неплохой стандартный учебник, в том числе на русском, в который я в любом случае рекомендую заглянуть: rurust.github.io/rust_book_ru/README.html . Правда, у С++ и Java тоже с этим особых проблем нет, разве что сложнее выбрать подходящий.


    Если вы всё же выбираете между C++ и Java - выбор в основном должен зависеть от того, сколько времени вы готовы потратить на изучение. Для изучения C++ нужно несколько лет (существует мнение, что около 5 лет), при этом нет смысла изучать C++ на базовом уровне - его достоинства проявляются только при хорошем знании языка. Java проще для изучения, довольно быстро можно достичь уровня, необходимого для устройства на работу, многие перспективные инструменты изначально разрабатываются на/для Java (например, экосистема BigData сейчас вертится вокруг Java и Scala, многие СУБД тоже ориентированы на Java). Но в случае выбора другого языка для изучения Java потом при необходимости можно будет быстро освоить, да и популярные инструменты обычно предоставляют интерфейсы для других языков, так что ориентироваться на конкретные инструменты не стоит.

    P.S. Я сам программирую на C++, Java (а чаще - Scala) использую только для научной работы (BigData и т.п.), и в целом C++ мне нравится больше. Но в будущем планирую перейти на Rust в качестве основного языка.
    Ответ написан
  • Как передать лямбду-функцию по ссылке, а затем присвоить в переменную?

    @Ariox41
    Для начала, сохранять функцию обратного вызова в глобальной переменной - уже плохая идея. Иногда имеет смысл сохранять call back в неизменной статической переменной, например, для ручной реализации таблицы виртуальных функций:
    static constexpr std::array<callbackType, n>
    Но к этому нужно подходить с осторожностью. Возможно, в глобальную (лучше - в статическую) переменную нужно сохранять не функцию, а как раз переменные, которые нужно захватить.

    Но если всё же хотите, должен сработать такой вариант:
    template<class Rt, class Fn>
    Rt static_capture(Fn fn){
      static Fn state = std::move(fn);
      return []{ 
         state();
      };
    }
    
    int main() {
      int localVar = 5;
      setit(static_capture<callbackType>([localVar](int num) {
        std::cout << num;
        std::cout << localVar;
      }));
    }


    Тут для каждой лямбды будет своя конкретизация шаблона и, соответственно, своя статическая переменная.

    Что касается std::function - в худшем случае она работает в два раза медленнее, чем обычные виртуальные функции. Можно написать свою реализацию специально для лямбд, которая будет работать чуть быстрее за счет меньшей универсальности, но принципиально ситуацию это не меняет - в большинстве случаев это незначительные расходы. Если всё же нужно оптимизировать - нужно менять архитектуру программы, передавать лямбды в качестве шаблонных параметров непосредственно к месту вызова, если это возможно (тогда они инлайнятся), использовать те же виртуальные функции и классические механизмы ООП.
    Ответ написан
    Комментировать
  • Какую вы знаете литературу о внутренностях С++?

    @Ariox41
    Многое из того, что вы хотите есть у Майерса. Он дает советы по использованию различных возможностей C++, в процессе разъясняя, почему нужно делать именно так (т.е. как оно работает), в каких случаях это не работает и почему у некоторых конструкций такой неудобный синтаксис. По C++03 - это "Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ", там есть немного устаревшие вещи, но для понимания причин добавления различных элементов в новые стандарты это даже полезно. Её дополняет "Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14" - там про новые стандарты, с предыдущей практически не пересекается.

    Много интересных статей на английском (точнее, ссылок на них) есть на https://www.reddit.com/r/cpp/ , но это больше для просмотра актуальных новостей, целенаправленно искать там что-то довольно сложно.
    Ответ написан
    Комментировать
  • Как подключить cxxtest к проекту с использованием IDE Clion?

    @Ariox41
    Не особо знаком с Clion и сххtest, но в CMake есть CTest, который позволяет добавлять произвольный исполняемый файл как тест (т.е. в CMakeLists указывается, что результат компиляции таких-то cpp файлов является тестом), и позволяет указывать аргументы командной строки при запуске теста. После конфигурации тесты запускаются командой make test или аналогичной для других систем сборки, что скорее всего можно прописать уже в настройках Clion: либо в настройках запуска проекта, либо как внешний инструмент.
    Ответ написан
    Комментировать
  • Как правильно написать тесты?

    @Ariox41
    Тестируется только интерфейс. Реализация для того и инкапсулирована, чтобы иметь возможность менять её произвольно, без зависимостей. Если реализация достаточно сложна для возникновения потребности в её тестировании - вам нужно вынести её в отдельные функции / классы, и тестировать уже их публичные интерфейсы как независимые модули.
    Ответ написан
    Комментировать
  • Что есть в C++, чего нет в C#?

    @Ariox41
    Принципиальное отличие C++ в том, что это язык с zero cost abstractions. Т.е. на нём можно реализовывать высокоуровневые абстракции, которые во время компиляции развернуться в код, эквивалентный коду на чистом c, написанному для решения той же задачи. Конечно, на практике всё не так гладко, многих функций C++ всё еще не хватает, но большинство других языков такой возможностью не обладают в принципе. Пока что для C++ реальным конкурентом в этом плане является разве что Rust, да и то скорее в будущем, чем в настоящем.
    Ответ написан
    Комментировать
  • Что читать после "Программирование: принципы и практика с использованием C++" Страуструпа?

    @Ariox41
    Майерса обязательно стоит почитать, хотя бы по диагонали. Начать лучше с "Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ" - там в основном про C++03, но большая часть всё еще актуальна. Затем можно переходить к "Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14".

    По многопоточному программированию на C++11 стоит почитать "Параллельное программирование на С++ в действии. Практика разработки многопоточных программ" Энтони Уильямса. По этой теме я ничего лучше пока не видел.

    Тут правильно говорят, что помимо чтения нужно еще и практикой заниматься, но придумать себе задачу обычно не просто. Я бы рекомендовал для начала изучать boost и пытаться запустить и модифицировать примеры из документации. Еще лучше - реализовывать эти примеры без копирования из документации. Это, конечно, не идеально, но лучше, чем ничего.
    Ответ написан
    Комментировать