Задать вопрос
Ответы пользователя по тегу C++
  • Почему в СТЕКЕ разрешается выделять достаточно мало памяти?

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

    Во-первых, потому что стек программе выделяется один раз сразу, а вот динамическую память все программы разделяют между собой. И пока одна программа ест гигабайт - вторая программа может жрать 10, а когда вторая завершится - первая может съесть эти 10 гигабайт. Со стеком так не получится, он должен быть непрерывен по адресам. И тогда каждой программе придется всегда выделять себе максимально возможный объем памяти, даже если он может не понадобится. Именно поэтому программы обычно не выделяют много стека.

    Во-вторых, часто неизвестно заранее, сколько и каких ресурсов надо будет выделять. Плюс ресурсы могут быть использованны в куче разных функций, а значит должны жить глобально или отдельно от какой-то одной функции (например в main), но тогда все будет в куче в одном месте и это тупо неудобно.

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

    Edit: да, если вам нужно больше стека, можно сделать так, чтобы программа получала больше стека. В С++ это делается параметром линкера.
    Ответ написан
    Комментировать
  • Как реализовать copy on write class?

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

    Нужен счетчик ссылок на буфер. Перед записью проверяйте, что счетчик равен 1. Иначе копируете данные и в текущем объекте заменяете указатель на новый буфер.

    Счетчик должен храниться где-то вместе с буфером и является частью умного указателя.

    Можно использовать std::shared_ptr - там уже этот счетчик реализован (use_count).
    Ответ написан
    Комментировать
  • Почему в массив записываются числа не и указанного диапазона?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    *p = (rand( )%100 - 50);
    for (int i = 1; i < k; i++) {
      *(p + 1) = -i * * (p + i - 1);
    }


    Можете вообще объяснить, что этот код делает? Зачем он это делает? Что вы хотели, чтобы он делал?

    Помимо этого, вместо *(p+X) можно писать p[X]. Так понятнее. У вас тут явно не к месту арифметика указателей приплетена.

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В деструкторе удаляйте, только если память не nullptr или длина не 0.
    Ответ написан
    Комментировать
  • Из за чего появляется ошибка ошибка ld returned 1 exit status?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Выше написанно undefined reference to 'processingArray(int*, int)'


    Ну вот. У вас функция processingArray объявлена, но нигде не реализована. Тело функции где? Поскольку вы ее объявили, компилятор это безобразие проглатил и понадеялся, что эта функция реализована в другом файле и на этапе линковки она найдется. Но линкер ее не нашел, потому что ее нигде и нет.

    Вы, видимо, не все из учебника переписали. Там после функции main скорее всего идет реализация функции processingArray.
    Ответ написан
    7 комментариев
  • Как решить проблему Segmention Fault?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Segmentation fault - это ошибка работы с памятью. Или выход за границы массива, или что-то не так с указателями.

    Я подозреваю, что в файле у вас не 50 строк (мне лень считать). Вот вы и вылезаете за границу массива.

    Ну или там какие-то лишние переводы строк, пробелы имеются. поэтому fin.eof() не выполняется после считывания последней строки. Потом вы пытаетесь что-то еще прочитать, но получаете назад пустую строку. Это бы не было проблемой, но вы потом пытаетесь это все запихать в 51-ый элемент массива.

    Советую вместо define N и статического массива использовать std::vector. В цикле считывания файла делайте push_back нового объекта в вектор (а еще лучше, emplace_back для экономии лишнего копирования).

    При выводе берите size() у вашего вектора.

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if ((matrix[i][j] < minValue[j]) && (isPartOfOutputTree[j] == false))


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

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

    Еще отдельная проблема с удалением первого элемента, потому что там менятся должна не ссылка next у предыдущего элемента, а ссылка на начало списка. Эту проблему можно решить по разному. Например, можно вместо указателя head держать один элемент списка без значения. Тогда указатель на начало списка будет менятся также как и любой другой. Фактически, в любом списке всегда будет один фиктивный элемент. Этот способ также предподчителен для работы с двусвязными списками. Тогда список как бы замыкается в кольцо и не надо разбирать отдельно ни случай первого, ни случай последнего элемента. Мне больше нравится другой метод - можно помнить не предыдущий элемент, а указатель-на-указатель, который надо будет поменять.

    node** prev_link = &head;
    node* cur = head;
    for  (node* cur = head; cur != nullptr; cur = cur->next) {
      if (cur->val == to_del) {
        *prev_link = cur->next;
        delete cur;
        break;
      }
      prev_link = &cur->next;
    }
    Ответ написан
    1 комментарий
  • Как исправить ошибку "Нарушение прав доступа при записи по адресу"?

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

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

    Можно во время отладки нажать на "продолжить" и тогда дебаггер остановится именно на той инструкции, которая вызвала ошибку. Дальше уже можно смотреть, в какую переменную вы там пишите и откуда она взялась.

    Падает оно потому, что нельзя string читать и писать в файл вот так, просто интенрпретируя память объекта как char*. Потому что string содержит в себе указатели на динамически выделенную память.

    Поэтому, когда вы его (в составе AutoBase) пишите в файл а потом читаете, вы получаете указатель на адрес, который был жив вместе со старым экземпляром класса. Однако, после удаления этого старого экземпляра, этот адрес уже вам не принадлежит.

    Вы можете так писать в файл только структуры из простых типов, и то не всегда (там всякое выравнивание может сыграть с вами злую шутку). Надо писать собственные методы сериализации и десериализации. Строку можно сохранять, например, как длину и потом столько байт, сколько нужно. Тогда при считывании вы сначала чистаете сколько-то байт размера, а потом нужное количество байт в саму строку.
    Ответ написан
    1 комментарий
  • Функция с параметром указателем на другую функцию. Как сделать правильно чтобы не выдавало ошибку?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    analiz(func(n));

    Вот тут вы вызываете функцию func и передаете результат ее работы в analiz. Хотя analiz хочет получать функцию. Надо делать так: analiz(&func);
    Ответ написан
    4 комментария
  • Как найти общую часть у вещественных чисел?

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

    Я думаю, вам остается только вывести оба числа в строки в каком-нибудь фиксированном формате и дальше сравнивать посимвольно.
    Ответ написан
  • Как лучше оптимизировать такие действия с массивами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Во-первых, может быть проблема со вводом. cin и cout работают медленно с большими объемами данных. Или читайте через scanf, или можно отключить синхронизацию с stdio.

    Во-вторых, описанная вами структура данных быстродействие не убъет, но мне не понятно, чем она поможет в задаче.

    Вам точно понадобятся map-ы из строки во что-то еще. В питоне вы наверняка использовали словари (использовали строки в виде ключа в массиве), вот это оно и будет в с++. Можно поэксперементировать std::unordered_map может быть побыстрее std::map. А вообще, особенно быстрое решение вы можете получить используя cтруктуру данных бор (оно же trie). Правда, ее придется самостоятельно писать.
    Ответ написан
    3 комментария
  • Можно ли реализовать графику на стандратных и системных библиотеках?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Да, конечно. Начиная от wingdi и заканчивая directx - Это все стандартные виндовые библиотеки.
    Ответ написан
    3 комментария
  • Почему транслятор ожидает указатель в моем коде?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Параметр функции int arr[],

    Но далее у вас arr[i][j]. Компилятор пытается взять индекс j, но перед ним же уже число. Вот он вам и говорит "начальника, индекс я у массива (указателя) взять могу, а тут число, непонятно".

    Вы обращаетесь с одномерным массивом, как будто бы он двумерный.
    Ответ написан
    Комментировать
  • Как при трансляции осуществляется связывание кода?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Зависит от того, как вы компилируете B. Если A туда не линкуется статически, то его придется отдельно указывать при компиляции EXE.
    Ответ написан
  • Как отсортировать данные структуры по алфавиту?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас заводится переменная str, и как и компилятор вам говорит, вы ее ничем не инициализируете. А ниже используете в strcpy(str, sot[i - 1].familia). Эта функция принимает указатель на область памяти, куда надо скопировать строку. Но указатель указывает на случайное место. Т.е. программа, даже если чудом скомпилируется, упадет с исключением.

    Вам надо или для str выделять память через malloc, или объявить str массивом char фиксированного размера, как поле familia у структуры.
    Ответ написан
    Комментировать
  • Теряются/бьются UDP пакеты на localhost, так и должно быть?

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

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

    Для поиска простых чисел лучше восспользоваться каким-то тестом на простоту, например тест Миллера-Рабина
    Ответ написан
    Комментировать
  • Не компилируется код. Как исправить ошибку?

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