Ответы пользователя по тегу C++
  • Почему не вызывается конструктор копирования при инициализации переменной другим объектом?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Тут сработало copy elision.

    operator& не создает никакого временного Query, а работает сразу с Query в месте его вызова. Поэтому конструктор в пункте 8 создает уже результат.
    Ответ написан
    Комментировать
  • Что делать с этой проблемой?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Исходник в кодировке utf. 'А' действительно занимает 2 байта. Что видит компилятор? Видит 2 байта между кавычками и ругается.

    setlocale() - эта функция во время исполнения программы настроит, в какой кодировке у вас будет просиходить ввод/вывод с консоли. На кодировку исходника оно никак не влияет.

    Тут 2 варианта решения: Или поменяйте кодировку исходника и настройки локали, чтобы 'А' занимало один байт, или работайте с wstring.

    Чтобы не путаться с кодировками, напишите программу, которая выводит численное значение байт прочитанной строки. Запустите ее, введите туда 'А', смотрите, что оно выводит. Поэксперементируйте с разными настройками setlocale(). Если выводит 2 байта - вот эти два байта надо писать в case и использовать wstring. Если выводит один байт, вот его в case и вставляйте.
    Ответ написан
  • Почему выдает ошибку при наследовании?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Для решения этой проблемы по уму надо написать вот это в определении производного класса:
    using Array<T>::_size;
    using Array<T>::_capasity;
    using Array<T>::_data;


    Ответ на вопрос "почему" в С++ всегда один: "потому что стандарт":
    Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:


    Проблема в том, что Array зависит от T, а вот его член _size от T не зависит. Ну вот не ищет компилятор независимые имена в зависимых местах. Независимые имена разрешаются в месте определения шаблона, когда еще неясно даже, с каким оно типом будет работать-то. Поэтому он никак до Array достучатся не может, ведь никакого T конкретного у него еще нет.

    Надо как-то компилятору указать, где искать вот эти ваши _size и т.д.
    Например, через this-> или через using или через Array<T>::.

    Вообще от этих правил lookup-а в C++ волосы дыбом встают и куча приколов вылезает. Их надо только запомнить. Оно неинтуитивно, но таково оно есть.
    Ответ написан
    Комментировать
  • Почему внутри шаблона можно иметь доступ к приватному члену внутреннего класса?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С чего вы взяли, что внутри шаблона это работет? Вы его инстанциировать пробовали (объявить переменную класса Outer<int>, например)?

    Вылезает точно такая же ошибка.

    Если шаблон просто написать, но не использовать его, то он компилироваться и не будет и ошибки в нем не обнаружатся.
    Ответ написан
    1 комментарий
  • Как проверить эфективность линейного и бинарного поиска в простом методе сортировки?

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


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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам повезло. Какой-то из включаемых вами других хедеров уже включает cstdint. Поскольку система инклудов в C++ идет еще из C и это дикое и неудобное легаси (текст хедера тупо вставляется в файл вместо include препроцессором), то такое рекурсивное включение работает.

    Но это плохая практика - стоит включать все, что вы используете всегда. Потому что потом вы что-то поменяете, исключив какой-то уже не нужный вам хедер отсюда, или из другого хедера, и у вас вылезет ошибка о неопределенных типах из cstdint.
    Ответ написан
    Комментировать
  • Какую роль играют float и double в скобках?

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

    float нужен вам в начале, потому что вещественные константы имеют тип double. Поэтому у eps/2.0 и 1.0 в первом цикле имеют тип double, все вычесляется в double. Преобразовав одно из выражений в float вы получаете то, что вам надо. Без этого все вычисления идут в double и ответ находится не тот. На самом деле там float при сравнении все-равно расширяется до double но на результат сравнения это не влияет в данном случае.

    Еще, вместо явного приведения типов, можно поставить f после вещественных констант, чтобы указать компилятору, что это float:
    while (1 + eps/2.0f != 1.0f){

    Тогда вычисления будут во float и ответ будет правильный.

    Во втором цикле double вам не нужен. Ведь вычисления итак идут в этом типе. Да и написано у вас там с опечаткой, вы к типу double приводите все выражение со сравнением. т.е. вы булево значение преобразуете в дабл. Потом оно назад в булево преобразуется при проверке условия циклом. В итоге это бесполезное действие.
    Ответ написан
    Комментировать
  • Крестики-нолики.Проблемы с ходом Х?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас там бесконечный цикл, который читает ход Х. Без единого break внутри - поэтому нет даже теоретической возможности, что вы из него выйдите.

    Упростите код: эти 9 if else условий заменяются на такой код:
    if (us.length() != 2) {
      cout << "?????" << endl;
      continue;
    }
    int row = us[0]-'A';
    int col = us[1]-'0';
    if (row < 0 || row > 2 || col < 0 || col > 2) {
      cout << "????" << endl;
      continue;
    }
    if (pole[row][col] != '_') {
      cout  << "занято" << endl;
      continue;
    }
    pole[row][col] = 'X';
    break;
    Ответ написан
    Комментировать
  • Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Да, может. Но обычно в самих конструкторах о многопоточном доступе не беспокоятся, потому что пока конструктор выполняется - объекта еще нет и никакой конкурентный доступ к нему невозможен. Если конструктор обращается к каким-то другим ресурсам, то вот те ресурсы должны защищаться от многопоточных проблем как обычно - не важно из конструктора к ним обращаются или из какого-то другого метода какого-то класса.
    Ответ написан
    Комментировать
  • Как запретить std:: vector перемещаться?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно через vector::reserve задать ему необходимый объем. Тогда он сразу же выделит все память и, если вы не будете в него класть больше этого размера элементы, он не будет перевыделять память вообще.

    Еще можно изменить ваш дизайн. Например, вместо vector использовать list, итераторы в котором не портятся от добавления. Или хранить вместо итераторов/указателей на элементы в векторе индексы.
    Ответ написан
    Комментировать
  • Можно в c++ ли работать с памятью через stream?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Класс std::stringstream как раз это и реализует.
    #include <stringstream>
    
    std::stringstream sout;
    sout << "some string " << 42;
    cout << sout.str();


    Но для сериализации эффективнее будет руками записывать данные в буфер через memcopy: все члены структуры по отдельности чтобы не было проблем с выравниванием. Для строк переменной длины надо будет писать еще и их размер отдельно. Для чисел надо аккуратно с порядком байт разобраться и писать их побайтово.
    Ответ написан
    Комментировать
  • Почему часто можно встретить отступление от структурного подхода?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Первый вариант легче читается. Особенно, если вариантов раннего выхода из функции несколько. Потому что меньше вложенность проверок, сразу видно что и при каких условиях возвращается.
    Ответ написан
    Комментировать
  • Как сравнить группу элементов в одномерном массиве в с++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Разбейте задачу на подзадачи:

    1) Проверить, что данный элемент надо удалить
    1.1) Проверить, что элемент не уникальный
    1.2) Проверить, что элемент - не первый среди одинаковых (один-то его надо оставить)
    2) Удалить элемент из массива дописав 0 в конце.

    Все эти пункты выполняются циклом. в первых пунктах будет удобно завести булевую переменную, которая после цикла будет содержать значение проверки.
    Ответ написан
    Комментировать
  • Почему T * может работать ощутимо быстрее (~ на 25-30%) в качестве хранилища данных, чем std::byte *?

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

    Создайте 2 функции, которые отличаются только вот в этих вот местах.
    Вставьте код в https://godbolt.org/

    Смотрите ассемблерный код для двух функций.

    Может, срабатывает strict aliasing. Видя тип T сомпилятор понимает, что эта переменная не может быть изменена какими-то другими std::byte в соседнем коде и может, например, пропустить загрузку-выгрузку данных в регистр из памяти.

    Может вообще что-то другое.

    Единственный вариант разобраться - это смотреть на ассемблерный код функций, которые вы и сравниваете. Не каких-то кусков, оттуда надерганных, а функций целиком.
    Ответ написан
    Комментировать
  • Ошибка Unhandled exception at 0x0099B514 in ConsoleApplication15.exe: 0xC0000094: Integer division by zero. Как исправить это?

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

    Засуньте ошибку в переводчик, если по английски не понимаете. Ну не умеют компьютеры нарушать законы математики - еще в школе же учат, что на ноль делить нельзя.

    Очевидно, что size/3 оказывается 0, потому что size меньше 3.

    Надо менять логику. Или отдельно обрабатывать случай size = 0,1,2 или не делить на 3. Вообще, неясно, откуда в этом коде 3 вылезло и что оно означает.
    Ответ написан
    Комментировать
  • Почему может быть ошибка во время компиляции?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема вот тут:
    parent.resize(++n);
    glub.resize(n);
    for (int i = 1; i <= n; i++) {


    Выход за границу массива. Неопределенное поведение.
    Вы выделяете массивы длины n (увеличенного на 1) и потом проходитесь от 1 до n (увеличенного на 1). Но ведь индексы в массиве только до n-1.

    Правильно так:
    parent.resize(n+1);
    glub.resize(n+1);
    for (int i = 1; i <= n; i++) {
    Ответ написан
    5 комментариев
  • Как реализовать идентификацию объектов?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    unordered_map<ID, Material>
    Ответ написан
    Комментировать
  • Ошибка ссылка на резрешенный внешний символ, как исправить в c++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Судя по ошибке, оно не может найти определение внутренних функций curl.

    Почитайте документацию библиотеки, надо в свойствах проекта добавить библиотеку curl линкеру.
    Ответ написан
    Комментировать
  • C++ как использовать функции winAPI?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вот это GetModuleHandle, например: Вводите в гугле "GetModuleHandle win32". Получаете ссылку вот сюда.

    Там прямо в заголовке написано libloaderapi.h
    Значит, вам надо делать #include "libloaderapi.h"

    Вот так по каждой интересующей вас функции надо найти документацию от microsoft. Там обычно написано, в какой библиотеке оно лежит и в каком заголовочном файле.

    Этот заголовочный файл является частью windows sdk.

    Как вызвать - смотрите в той же документации, какие параметры функция принимает. Или гуглите "GetModuleHandle example".
    Ответ написан
  • Где ошибка в коде переворота двумерного массива?

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

    Надо отдельно обработать случай y == y1
    Ответ написан
    Комментировать