• Почему программисты не любят возврат константных ссылок в C++?

    Если предоставляется доступ к ресурсам текущего объекта, то возвращаемое значение -- ссылка (константность зависит, конечно, от того, запрещаем ли мы изменять эти данные). Иначе -- значение.
    А теперь представим, что есть виртуальный класс Window с методом title. Как подклассы Window будут хранить title -- деталь реализации, но в getter они по контракту обязаны привести его к std::string. Отсюда и возврат по значению: в каком типе хранится значение -- деталь реализации.
    Ответ написан
    Комментировать
  • Добавление в динамический массив объектов. Кто поможет?

    Совет номер 1: используйте std::vector вместо массива. Это правда проще!
    Совет номер 2: используйте именно вектор от Patient, то есть по возможности не используйте указатели для хранения объектов.

    > Таким образом, как я передаю объект в метод, я смогу изменять его? Это то же, что и передача через указатель?
    Да, ссылки -- это, по сути, удобные указатели.
    > а что бы изменилось если бы я передавал через указатель?
    Пришлось бы писать лишние разыменования.
    Ответ написан
    24 комментария
  • Как увеличить счетчик в qt?

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

    Копируем символы отсюда (раздел DOS) в строки в программе, главное -- правильно расположить все границы и углы.
    Ответ написан
    5 комментариев
  • Как объявить перегрузку оператора вне класса C++?

    Zespolona operator+(const Zespolona& left, const Zespolona& right) { ... }
    Zespolona operator-(const Zespolona& left, const Zespolona& right) { ... }

    Внутри самого класса нужно добавить friend-объявления:
    friend Zespolona operator+(const Zespolona& left, const Zespolona& right);
    friend Zespolona operator-(const Zespolona& left, const Zespolona& right);
    Ответ написан
    5 комментариев
  • Как конвертировать MapKit MKCoordinateSpan в Float|Int для Google Maps?

    Если нужно просто преобразовать тип числа из Double во Float, то в Swift это выполняется с помощью конструктора:
    let coordinateSpan: MKCoordinateSpan = ...
    let latitudeFloat = Float(coordinateSpan.latitudeDelta)
    let longitudeFloat = Float(coordinateSpan.longitudeDelta)
    Ответ написан
  • Почему массив заполнился буквой H?

    Память не инициализирована, поэтому там мусор. Что именно -- Unspecified Behavior.
    Ответ написан
    6 комментариев
  • Чему будет равно i при таком необычном указателе?

    1028. При инкременте указателя к нему добавляется sizeof от того, на что он указывает, то есть
    i++;
    эквивалентно
    (int&)i += sizeof(uint32_t);

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

    Используйте передачу по ссылке:
    for (auto& neuron : neurons)

    Иначе при обходе цикла вы скопируете весь массив. А то, что конструктор вызывается только вначале, — очень странно, скорее всего, это ещё один баг. Можно увидеть всё объявление класса neuron (без реализации функций)?
    Ответ написан
  • Как неопределенное поведение в javascript складывается на уровне V8?

    NaNNaNNaNNaNNaN Batman!
    Если серьёзно, то это неявные приведения типов операндов. Вот отличное объяснение.
    Ответ написан
    5 комментариев
  • Существуют ли языки компилируемые в C++?

    Если вы реализуете API, совместимый с C, то можно линковаться с любым компилируемым языком, например, Rust. Другое дело, что при этом теряются все плюшки C++, API будет выглядеть, скажем так, не идеально.
    Ответ написан
    Комментировать
  • Передача функции - шаблоны или std::function?

    Первый вариант:
    template<typename Func> void MyFunc (const Func & otherFunc);

    Гарантирует, что otherFunc будет заинлайнена в MyFunc, то есть такой вариант предпочтителен там, где требуется максимальная производительность. Но шаблонные функции не могут быть виртуальными. То есть такой вариант очень хорошо подходит для функций-утилит, и плохо подходит для методов публичного API и на границах модулей, так как там как раз инлайн не нужен, а нужны виртуальность и сокрытие реализации.

    Важное замечание! Приведённый код не совсем корректен, всегда в таких случаях используйте передачу по универсальной ссылке:
    template<typename Func> void MyFunc (Func&& otherFunc);

    Такой вариант покрывает и константные функторы, и те, которым необходима мутабельность для работы. Если вы планируете сохранить функтор, то это ещё и позволит воспользоваться perfect forwarding -- по сути, единственный способ, корректно работающий с любым переданным функтором:
    field = std::forward<Func>(otherFunc);

    Второй вариант:
    void MyFunc (const auto & otherFunc);
    Можно использовать, если вам не нужен тип функтора. По сути он эквивалентен предыдущему.

    Третий вариант:
    void MyFunc (const std::function<void()> & otherFunc);

    Возьмите отрицание моих предыдущих аргументов и примените сюда. Можно использовать с виртуальными функциями, больше подходит для API, но теряет в производительности. А именно, вызов otherFunc эквивалентен вызову виртуальной функции.

    Четвёртый вариант:
    void MyFunc (const void (&otherFunc)());
    Работает только с простыми, глобально определёнными функциями. Вместо этого практически всегда стоит использовать std::function.
    Ответ написан
    Комментировать
  • Лучший вариант проверки ввода на несколько условий в C++?

    Можно немного упростить код:
    while (true) {
      cin>>x;
      if (x < 0) {
        cout<<"x должно быть положительным числом"<<endl;
      } else if (x == 0) {
        cout<<"x не должно равняться нулю"<<endl;
      } else if (x == 5) {
        cout<<"x не должно равняться пяти"<<endl;
      } else {
        break;
      }
    }
    Ответ написан
    Комментировать
  • Почему не получается заполнить структуру в СИ?

    Поправьте 2 строчки:
    scanf("%d", &airport[i].numr);
    // =>
    scanf("%d\n", &airport[i].numr);

    printf("\n%d", airport[i].numr);
    // =>
    printf("%d\n", airport[i].numr);
    Ответ написан
  • Как отсортировать строки в алфавитном порядке в СИ?

    Нужно воспользоваться qsort.
    Функция сравнения:
    int compare_prices(const void* price1, const void* price2) {
        const char* name1 = ((const price*)price1)->name;
        const char* name2 = ((const price*)price2)->name;
        return strcmp(name1, name2);
    }

    Вызов qsort:
    qsort(МАССИВ_СТРУКТУР, РАЗМЕР_МАССИВА, sizeof(price), &compare_prices);
    Ответ написан
    Комментировать
  • Почему string - это char*?

    Я так понял, что std::string не имелся в виду.
    То есть суть вопроса такова: почему строки передают как char*, хотя это тип указателя на один char.

    Дело в том, что массивы в C нельзя передавать как параметр функции, указатель на массив нельзя сохранить.
    В результате массив, например char[8], принято передавать как указатель на его первый элемент: char*. Более того, при передаче массива в функцию он автоматически разлагается (decays) до указателя на первый элемент.

    Остальные элементы получаются при помощи адресной арифметики: *(p+3) или p[3], что одно и то же. Итак, указатель в коде C может указывать как на одну переменную, так и на целый массив (точнее, его начало).

    Для массивов int или любого другого типа обычно вместе с указателем на первый элемент передают размер массива. Но строки C завершаются нулевым символом, поэтому здесь длина известна и так. Вот и получается, что char* используют вместо char[N].

    Edit: На самом деле, в C можно объявить указатель на массив:
    int (*arr)[10] = malloc(sizeof(*arr) * 5);
    Не помню, чтобы я видел такую конструкцию в реальном коде.
    Ответ написан
    1 комментарий
  • Ошибка: no matching constructor for initialization, что делать?

    Неправильно объявлен конструктор копирования и оператор присваивания:
    TemplateRequirement(TemplateRequirement &);
    TemplateRequirement& operator=(TemplateRequirement&);

    Надо так:
    TemplateRequirement(const TemplateRequirement &);
    TemplateRequirement& operator=(const TemplateRequirement&);

    Ещё советую заменить параметры типа QString и QString& на const QString&.
    Ответ написан
    3 комментария
  • Как создать палитру цветов для bmp изображения?

    Можно применить Median cut.
    Суть алгоритма заключается в следующем:
    1. Создаём одну корзину (вектор) со всеми пикселами изображения
    2. Определяем цветовую компоненту (R, G или B), по которой диапазон значений (max - min) в корзине наибольший
    3. Находим медиану этого цвета и разбиваем корзину на две
    4. Повторяем шаги 2 и 3 до достижения нужного числа корзин
    5. Далее можно, например, найти в каждой корзине средний цвет и создать std::unordered_map из текущего цвета в усредненный
    Ответ написан
    Комментировать
  • Как превратить очередь в 2 очереди?

    Не разобрался, в чем проблема, вот рабочее решение:
    spoiler
    #include <stdlib.h>
    #include <stdio.h>
    
    struct TNode {
    	int data;
    	struct TNode *next;
    };
    typedef struct TNode Node;
    
    struct TQueue {
    	Node* head;
    	Node* tail;
    };
    typedef struct TQueue Queue;
    
    Queue* newQueue()
    {
    	Queue* queue = malloc(sizeof(Queue));
    	queue->head = NULL;
    	queue->tail = NULL;
    	return queue;
    }
    
    void deleteQueue(Queue* queue)
    {
    	Node* current = queue->head;
    	while (current != NULL) {
    		Node* next = current->next;
    		free(current);
    		current = next;
    	}
    	free(queue);
    }
    
    void pushBackQueue(Queue* queue, int data)
    {
    	Node* newNode = malloc(sizeof(Node));
    	newNode->data = data;
    	newNode->next = NULL;
    
    	if (queue->tail == NULL) {
    		queue->head = newNode;
    		queue->tail = newNode;
    	}
    	else {
    		queue->tail->next = newNode;
    		queue->tail = newNode;
    	}
    }
    
    void splitQueue(Queue* source, Queue* even, Queue* odd)
    {
    	for (Node* current = source->head; current != NULL; current = current->next) {
    		int data = current->data;
    		pushBackQueue((data % 2 == 0) ? even : odd, data);
    	}
    }
    
    void printQueue(Queue* queue)
    {
    	for (Node* current = queue->head; current != NULL; current = current->next) {
    		printf("%d ", current->data);
    	}
    	printf("\n");
    }
    
    int main()
    {
    	Queue* source = newQueue();
    	for (int i = 0; i < 20; i++) {
    		pushBackQueue(source, i + 1);
    	}
    	printQueue(source);
    
    	Queue* even = newQueue();
    	Queue* odd = newQueue();
    	splitQueue(source, even, odd);
    	printQueue(even);
    	printQueue(odd);
    
    	deleteQueue(source);
    	deleteQueue(even);
    	deleteQueue(odd);
    
    	system("pause");  // not needed in Linux
    	return 1;
    }


    И лучше убрать C++ из заголовка, иначе возникают вопросы типа "почему без классов" и "почему не std::linked_list".
    Ответ написан
    2 комментария
  • Как правильно построить структуру программы?

    Поиграйтесь с cv::rectangle, cv::addWeighted и cv::putText.
    Вот код прямиком из рабочего проекта, рисует полупрозрачный прямоугольник и пишет строки текста:

    cv::Mat writeOnImage(const cv::Mat& source, const std::vector<std::string>& lines, int width)
    {
    	auto rect = source.clone();
    	cv::rectangle(rect, { 10, 10 }, { width, 20 + 50 * static_cast<int>(lines.size()) }, cv::Scalar(0, 0, 0), cv::FILLED);
    
    	auto result = cv::Mat();
    	cv::addWeighted(source, 0.6, rect, 0.4, 0.0, result);
    
    	for (size_t i = 0; i < lines.size(); ++i) {
    		cv::putText(result, lines[i], { 20, 50 + 50 * static_cast<int>(i) }, cv::FONT_HERSHEY_PLAIN, 3, cv::Scalar(10, 255, 255), 3, cv::LINE_8);
    	}
    
    	return result;
    }
    Ответ написан
    1 комментарий