Ответы пользователя по тегу C++
  • Инкремент и декремент?

    @res2001
    Developer, ex-admin
    Постфиксный вариант используют в основном, когда очень хочется минимизировать исходный код программы - вместо двух строчек кода, написать одну.
    Реального выигрыша (кроме количества строчек исходного кода) от этого обычно нет. Но иногда становится сложнее понимать написанное.

    Префиксный вариант проще в реализации, а значит работает чуть быстрее. При большом количестве итераций в цикле это может иметь некоторое значение. В префиксном варианте нет "отложенных эффектов", из-за которых в постфиксном варианте могут возникать ошибки.
    Ответ написан
    Комментировать
  • Безопасно использовать типы atomic из Си в динамических структурах?

    @res2001
    Developer, ex-admin
    Атомарные переменные - это такие же переменные как и остальные. Инициализировать их вы можете сколько угодно раз. Это относится только к встроенным типам. Атомарные классы - это сказка.
    Но на них накладываются некоторые ограничения:
    1. выравнивание переменной - переменная должна находится по адресу обычно кратному размеру переменной. Если не будет правильного выравнивания, то intelовские процы могут сделать 2 операции чтения, что уже не будет атомарной операцией. Другие процы могут сгенерировать какое-нибудь исключение.
    2. атомарная переменная всегда volatile - т.е. компилятор не может ее кэшировать в регистре, всегда идет обращение к памяти.
    Не все атомарные переменные в std действительно атомарны. Это проверяется с помощью atomic_is_lock_free(). Атомарность зависит от платформы. Например на x86 int64 - не атомарна из-за ограничений процессора. Тогда как на 32 битных АРМах она вполне атомарна.
    При обычном чтении/записи атомарных переменных (с упорядочиванием памяти memory_order_seq_cst) происходит синхронизация кэшей ядер - из-за чего атомарные операции "дороже" не атомарных. Но этот процесс на разных архитектурах стоит по разному. Для синхронизации кэшей есть отдельные ассемблерные инструкции.

    В целом все undefined behavior для атомарных переменных в std связаны с:
    1. возможностью объявить атомарным любой класс
    2. не для всех встроенных типов на конкретной платформе гарантируется реальная атомарность (atomic_is_lock_free).
    3. если вы не будете соблюдать ограничения, то же ничего гарантировать нельзя.
    Так что особо пугаться undefined behavior не стоит. Просто соблюдайте ограничения, не используйте атомарные классы и удостоверьтесь, что встроенные типы на вашей платформе действительно атомарны.
    Ответ написан
    1 комментарий
  • Вывести вместо пробелов введенной строки его ASCII-код?

    @res2001
    Developer, ex-admin
    Просто преобразуйте символ в int и выводите.
    char a = ' ';
    std::cout << "ASCII code: " << static_cast<int>(a) << std::endl;
    Ответ написан
    1 комментарий
  • Как комбинировать несколько значений из одного enum?

    @res2001
    Developer, ex-admin
    Битовые операции можно использовать только если ваш enum состоит из значений равных степеням двойки: 1, 2, 4, 8, ...
    Если у вас произвольные значения в enum (1, 2, 3, 105, 888, ...) то битовые операции применять нельзя.
    Если нужен какой-то универсальный вариант - сделайте массив значений.
    Ответ написан
    Комментировать
  • Как можно оптимизировать код?

    @res2001
    Developer, ex-admin
    Может быть, если конвертировать число в строку и проверять строку на палиндром, будет быстрее. Не уверен, надо проверять. Только не используйте std::string, а используйте стандартный сишный массив символов.
    Ответ написан
    Комментировать
  • Вывод без использования iostream?

    @res2001
    Developer, ex-admin
    std - это внешняя библиотека. Хоть она и "стандартная", но не является неотъемлемой частью языка. Например, можно писать программу, не используя стандартную библиотеку - довольно забавное занятие. Попробуйте вывести "Hello world" или выделить буфер в динамической памяти без std .

    Поэтому необходимы почти все стандартные действия для подключения дополнительных библиотек:
    1. Включение заголовочных файлов - первое из этих действий.
    2. Второе действие - линковка с библиотекой исполняемого файла программы - выполняется по умолчанию большинством компиляторов. Наоборот для отключения линковки с std нужно указывать дополнительные ключи. Для других библиотек этот пункт нужно выполнять разработчику явно (указывать необходимые опции компилятору).

    Кроме того std довольно большая библиотека и ее полное включение по умолчанию во все исходники сильно бы увеличило время компиляции.
    Ответ написан
    Комментировать
  • Указатель или Индекс элемента?

    @res2001
    Developer, ex-admin
    имею ввиду, зачем делают так *p+1 для доступа к следующиму элементу, а не p[1]?

    Вообще то ничего общего между приведенными операциями нет (смотрите приоритет операций):
    *p+1 == (*p) + 1
    p[1] == *(p+1)


    Но вопрос в целом понятен, не взирая на ошибку в примере.
    Надо смотреть на контекст. Часто бывает, что код не ограничивается одноразовым применением p[1], а например есть целая серия обращений к p[1], в этом случае будет экономия на операциях, если вы сначала вычислите адрес p[1], а в дальнейшем будете использовать простое разыменование этого адреса. Будет ли реально выигрыш во времени исполнения зависит от компилятора, в целом думаю, современные компиляторы в состоянии сами сделать подобную оптимизацию.
    Ответ написан
    Комментировать
  • Что же такое typedef class, typedef struct?

    @res2001
    Developer, ex-admin
    Все то же самое, что и для других типов.
    Эти записи идентичны:
    typedef class ca {
    ...
    } CA;


    class ca {
    ...
    };
    typedef ca CA;
    Ответ написан
    Комментировать
  • Как правильнее будет использовать оператор if?

    @res2001
    Developer, ex-admin
    Всегда, когда это возможно, использую второй вариант - это позволяет избежать лишних фигурных скобок, а как следствие лишней вложенности, отступов и т.п., код становится более читабельный и простой.
    Но, конечно, в этом случае, в теле if должна быть передача управления куда-то (на обработчик ошибок, return и т.п.).
    Часто делаю такую конструкцию:
    do {
    ...
    if(result == error) break;
    ...
    } while(0);
    if(result == error) {
    обработка ошибок
    }

    В этом случае обработка ошибок находится в одном месте. Кроме того do..while(0) позволяет не использовать goto - вместо него используется break. Часто видел подобную схему в около системных сервисах и утилитах, но с использованием goto. У меня аллергия на goto, поэтому предпочитаю заворачивать в do..while(0).
    Ответ написан
    Комментировать
  • Как сопоставить 2 массива в цикле по ключам?

    @res2001
    Developer, ex-admin
    В массивах С++ нет ключей, там есть числовые индексы элементов от 0 до N-1.
    Ответ написан
    Комментировать
  • Как перевести ANSI в UTF-16 LE?

    @res2001
    Developer, ex-admin
    В WinAPI MultiByteToWideChar доступна для всех языков.
    Ответ написан
  • Вопрос о использовании mutex и lock_guard?

    @res2001
    Developer, ex-admin
    И получается участок кода(с создания переменной и до вызова диструктора) код будет выполняться только одним потоком?

    Как напишете, так и будет выполнятся.
    По моему не зачем зашивать lock_guard в структуру/класс, он должен быть в функции/методе тут же создаваться и удаляться максимально быстро. Если это приведет к дополнительному коду - это небольшая расплата за потокобезопасность.
    Ответ написан
    Комментировать
  • При изучении фабричного метода, увидел странную структуру, что это?

    @res2001
    Developer, ex-admin
    Публичное наследование.
    Так же может быть и приватное наследование и защищенное наследование.
    Обычно не указывается, т.к. по умолчанию оно и так публичное.
    Ответ написан
    6 комментариев
  • Что делает эта часть кода (выделено кругом)?

    @res2001
    Developer, ex-admin
    Это конструктор копирования класса myclass, принимает в параметре константную ссылку на экземпляр класса myclass. Вызывается для того, что бы создать новый экземпляр класса на основе уже существующего экземпляра этого же класса (скопировать класс).
    Подробности и примеры смотрите тут: https://en.cppreference.com/w/cpp/language/copy_co...
    Ответ написан
  • В чем ошибка в программе?

    @res2001
    Developer, ex-admin
    Реализовано не правильно, конечно.
    Но начнем с начала:
    подстановке значений переменных выходит тот же результат, что и при обычном выполнении.

    Что вы хотите этим сказать? Смысл этого заявления не понятен.
    int X; { // ввод переменной
         cout <<"X\n"; // вывод переменной на экран
        }

    В этом куске кода ввода переменной Х нет. Есть только вывод Х. Но выводится "Х", а не значение переменной. Кроме того переменная Х только объявлена, но не проинициализирована.
    Не достаточно написать в комментарии "ввод переменной", чтоб появился ввод. Надо написать инструкции ввода.
    Ну и т.д.
    Ответ написан
  • Как решается задача?

    @res2001
    Developer, ex-admin
    Идешь в цикле по годам, начиная с 2013. В цикле:
    1. вычитаешь из текущих запасов выловленные в этом году 50 т.
    2. прибавляешь к текущим запасам воспроизводство в этом году 30 т.
    3. выводишь статистику запасов
    4. если запасов стало меньше 50 т., то завершаешь цикл.
    Ответ написан
    2 комментария
  • Как сократить запись?

    @res2001
    Developer, ex-admin
    if(std::strpbrk(String.c_str(), " ,.?") != nullptr_t)
    {
    }
    Ответ написан
    Комментировать
  • Как повторно просить ввести данные пока не введут верные?

    @res2001
    Developer, ex-admin
    Не о том спрашиваете.
    Любой цикл можно использовать:
    for(;;) {...}
    while(true) {...}
    do {...} while(true)

    Выходить из цикла с помощью break, когда ввод будет нормальный или изменить условие цикла.
    На самом деле вечный цикл в данном случае не нужен. Лучше всего предусмотреть, например, 3 попытки ввода, и если не удачно - завершаемся. В этом случае for() подойдет лучше всего.
    В целом в С/С++ циклы for и while имеют одинаковую функциональность, но for более приспособлен для счетчиков и т.п., т.к. в нем инициализация, условие и концовка цикла собраны в одной строке (более компактно, чем while). То же самое можно сделать и в while, но инициализацию и концовку придется написать отдельно.
    Ответ написан
    1 комментарий
  • Где ошибка в програме?

    @res2001
    Developer, ex-admin
    Этот вопрос лучше всего задать компилятору - он вам скажет где ошибка. Просто откомпилируйте программу.
    Если вам будет не понятно сообщение компилятора, то приложите его сюда вместе с кодом. Так будет всем проще.
    Если не считать странных пустых скобок при определении x и y, то ошибка в 0,345 - разделитель дробной части в плюсах точка. Так же не понятно выражение: (1, 64 - 2*y) - оно откомпилируется без ошибок, но вычислит ли оно то что вы задумали - врят ли: наверняка вы имели ввиду (1.64 - 2*y) - не правильный разделитель дробной части и лишний пробел, то же с 12.6, 3/7 - даст в результате 0, т.к. это целочисленное деление.
    Ответ написан
    Комментировать
  • Как решить ошибки в коде?

    @res2001
    Developer, ex-admin
    Посмотрите, как правильно обращаться с перечислениями: https://en.cppreference.com/w/cpp/language/enum
    Тот вариант обращения к перечислению, который вы используете в коде называется Scoped enumerations. Чтоб его использовать вы должны объявить Direction так: enum class Direction {....
    Если же перечисление объявлять так как у вас, то обращаться к нему нужно без указания Direction.
    Ответ написан