Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.77/22: Рейтинг темы: голосов - 22, средняя оценка - 4.77
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30

Избыточное копирование объекта при реализации оператора умножения и оператора присваивания

21.03.2016, 18:43. Показов 5106. Ответов 84
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть класс работы с матрицами. Есть операция умножения матриц, описанная как оператор класса. В данном коротком примере я просто моделирую ситуацию. Реальное наполнение класса принципиальной разницы не играет, нужно просто понимать, что оператор умножения будет иметь большой код, оператор присваивания в реализации тоже будет не пустым. Эти места в примере засвечены комментариями

C++
#include <cstdio>
 
class Matrix
{
  private:
    // внутренние данные матрицы
 
  public:
    Matrix ();
    Matrix (const Matrix&);
    ~Matrix ();
 
    Matrix& operator=(const Matrix& a);
    Matrix operator*(const Matrix& a) const;
};
 
Matrix::Matrix ()
{
  printf ("Matrix ()\n");
};
 
Matrix::Matrix (const Matrix&)
{
  printf ("Matrix (const Matrix&)\n");
};
 
Matrix::~Matrix ()
{
  printf ("~Matrix ()\n");
};
 
Matrix& Matrix::operator=(const Matrix& a)
{
  printf ("operator=(const Matrix&)\n");
 
  // тут как бы код, копирущий данные из "a" в "this"
 
  return *this;
}
 
Matrix Matrix::operator*(const Matrix& a) const
{
  printf ("operator*(const Matrix&)\n");
 
  Matrix result;
 
  // тут как бы код, умножающий "a" и "this" и записывающий
  // данные в "result"
 
  return result;
}
 
Matrix a, b, c;
 
int main (void)
{
  printf ("------------------\n");
  a = b * c;
  printf ("------------------\n");
}
Исполнение:

Code
$ g++-4.8 t.cc
$ ./a.out
Matrix ()
Matrix ()
Matrix ()
------------------
operator*(const Matrix&)
Matrix ()
operator=(const Matrix&)
~Matrix ()
------------------
~Matrix ()
~Matrix ()
~Matrix ()
Нас интересует только фрагмент печати внутри функции main (т.е. между палками)

Посмотрим на ассемблерный код. Компилирую с опцией -fno-inline, чтобы оставаться с короткой программой и не разводить геморрой по борьбе с inline'ом со стороны компилятора. В общем случае тела операторов класса Matrix будут в отдельном файле и НЕ будут доступны для inline'а. Опцию -fno-exceptions подаю, чтобы было меньше мусора в коде

Code
$ g++ t.cc -O2 -fno-inline -fno-exceptions
$ cat t.s
...
    leal    -9(%ebp), %ebx
    subl    $32, %esp
    movl    %ebx, (%esp)
    movl    $c, 8(%esp)
    movl    $b, 4(%esp)
    call    _ZN6MatrixmlERKS_  <- operator*
 
    subl    $4, %esp
    movl    %ebx, 4(%esp)
    movl    $a, (%esp)
    call    _ZN6MatrixaSERKS_  <- operator=
...
Таким образом мы видим, что построился код, схематично эквивалентный следующему примеру на Си. На всякий случай напоминаю, что с точки зрения семантики C++ выражение "a = b * c" трактуется как "a.operator= (b.operator* (c))"

C
typedef struct { /* внутренности */ } Matrix;
 
extern void operator_assign (Matrix *this, const Matrix *value);
extern void operator_mul (Matrix *result, const Matrix *this, const Matrix *operand2);
 
Matrix a, b, c;
 
int main (void)
{
  Matrix tmp;
 
  operator_mul (&tmp, &b, &c); /* tmp = b.operator* (c) */
  operator_assign (&a, &tmp);  /* a.operator= (tmp) */
}
Мы видим, что в этом коде делается ненужное действие в виде лишнего оператора присваивания. Для умножения матриц эффективный код на Си выглядел бы как

C
operator_mul (&a, &b, &c);
т.е. без заведения промежуточной переменной и дополнительного копирования (которое представляет собой ненужные накладные расходы)

Вопрос. Как правильно написать текст на C++, чтобы получить код, эквивалентный вышеприведённой эффективной реализации на C? Оставаясь при этом в объёме стандарта C++98. Оставляя исходник в понятном и читабельном виде, без использования извращений типа семиэтажных шаблонов и т.п.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.03.2016, 18:43
Ответы с готовыми решениями:

Неправильная работа оператора присваивания после работы оператора суммирования
Доброго времени суток. У меня есть класс вектор class TVector {//ewde public: TVector(); //Vector(Vector &amp;v); ...

От каких ошибок страхует Const при перегрузке оператора присваивания
Здравствуйте. Вопрос имею теоретический. В классе A перегружается оператор присваивания, объявление выглядит так: const A operator =...

Почему при перегрузке оператора присваивания, возвращаемое значение не константно?
Почему при перегрузке оператора присваивания, возвращаемое значение - someClass &amp; operator=(const someClass&amp; rhl), а не const...

84
22.03.2016, 15:02
Студворк — интернет-сервис помощи студентам

Не по теме:

Renji, если вы используете матрицу 2x2, которая заполняется сразу("за раз"),
и таких матриц много - имеет смысл использовать соответствующую возможным значениям
матрицы строгую адресацию, соответствующую количеству матриц. причём адресацию с запасом,
позволяющим адресовать непрерывный "диапазон" одинаковых значений. одно или двумерный

0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 15:26
Evg,
Цитата Сообщение от Evg Посмотреть сообщение
a = a * a;
Как здесь обойтись без дополнительной памяти? Требовать, чтобы слева и справа не было одних и тех же матриц?
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.03.2016, 15:46  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
ничего вам не напоминает ASM vs C ?
Нет, не напоминает. Хотя бы потому, что опять-таки условные 90% тех, кто считает, что умеет программировать на ассемблере, попросту не смогут написать код перемножения матриц на ассемблере, чтобы он был быстрее, чем из-под компилятора Си

Цитата Сообщение от Nosey Посмотреть сообщение
Приведите примеры, желательно с тестами показывающие разницу, другого способа убедиться что С++ подход в результате не хуже я не знаю
Зачем? Делать мне больше нечего, как тебя в чём-то переубеждать? За конкретным примером далеко ходить не надо, он написан в первом посте данной темы. И пока до сих пор никто не привёл код на Си++, который бы работал столь же быстро, как и эквивалентный "эффективный" код на Си

Цитата Сообщение от Kastaneda Посмотреть сообщение
Вместо
a = b * c;
написать
(a = b) *= c;
понятно, что нужно реализовать *=
При таком подходе изменяется значение b. Что делает пример совсем не эквивалентным

Цитата Сообщение от avgoor Посмотреть сообщение
Как здесь обойтись без дополнительной памяти?
Да, тут соглашусь с претензией, она справедлива в том числе и для реализации функции operator_mul. Но для эффективной реализации мы действительно можем потребовать, чтобы dst не совпадал ни с одним из src. Я не специалист по математике, возможно, что есть алгоритмы, которые действительно требуют аккумулировать значение и работать операциями вида a *= b. Если задача требует подобных операций, то память, необходимую для вычисления произведения матриц, можно нормально выделять локально в стеке практически бесплатно (в отличие от динамической памяти, выделяемой всякими new). Хотя в таком варианте получится уже далеко не Си++ , потому что придётся работать с указателями, а не с ссылками

Во всяком случае твоя претензия помогла мне интуитивно понять, почему "стандартными средствами C++" мою постановку задачи В ОБЩЕМ СЛУЧАЕ не решить без промежуточного копирования
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 15:55
Цитата Сообщение от Evg Посмотреть сообщение
Я не специалист по математике, возможно, что есть алгоритмы, которые действительно требуют аккумулировать значение и работать операциями вида a *= b. Если задача требует подобных операций, то память, необходимую для вычисления произведения матриц, можно нормально выделять локально в стеке практически бесплатно (в отличие от динамической памяти, выделяемой всякими new). Хотя в таком варианте получится уже далеко не Си++ , потому что придётся работать с указателями, а не с ссылками
Зависит много от чего. Например: размерность матрицы - это поле класса или параметр шаблона? Может это вообще разреженые матрицы итд.
В общем случае - тут тернарная операция, и реализовать ее как две бинарных - не получится.
Исходя из вышесказанного: Matrix::inplace_mul(const Matrix& l, const Matrix& r) так, наверное.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
22.03.2016, 15:56
Цитата Сообщение от Evg Посмотреть сообщение
При таком подходе изменяется значение b
???
C++
1
2
3
4
5
6
7
8
Matrix& Matrix::operator=(const Matrix& a)
{
  printf ("operator=(const Matrix&)\n");
 
  // тут как бы код, копирущий данные из "a" в "this"
 
  return *this;
}
operator = вернет ссылку на a, для которого уже будет вызвать *=. b тут меняться не будет.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 16:04
Evg, В принципе можно возвращать из operator* кортеж {Matrix*, Matrix*} и в operator=(std::tuple реализовать умножение. В общем возвращать прокси.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.03.2016, 16:26  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
operator = вернет ссылку на a, для которого уже будет вызвать *=. b тут меняться не будет
Ну да, моск заклинило. Но лишнее присваивание a=b таки будет исполнено (перед тем, как выполнить умножение). Ибо

Цитата Сообщение от avgoor Посмотреть сообщение
В общем случае - тут тернарная операция, и реализовать ее как две бинарных - не получится
-----------------

Цитата Сообщение от avgoor Посмотреть сообщение
Исходя из вышесказанного: Matrix::inplace_mul(const Matrix& l, const Matrix& r) так, наверное.
Ну это эквивалентно примеру на Си. Т.е. уже известный вариант решения

Цитата Сообщение от avgoor Посмотреть сообщение
Evg, В принципе можно возвращать из operator* кортеж {Matrix*, Matrix*} и в operator=(std::tuple реализовать умножение
Но это уже C++11. Я тут не знаю, как всё это описать синтаксически, а потому не смогу себе родить исходник для анализа построенного кода. Но идею понял. Правда подозреваю, что перестанут работать выражения типа "a = b * c + d" или вызовы функций типа "foo (a * b)". Т.е. вариант с кортежами ограничивает написание кода лишь выражениями в одну операцию с обязательным qприсваиванием
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 16:33
Цитата Сообщение от Evg Посмотреть сообщение
Т.е. вариант с кортежами ограничивает написание кода лишь выражениями в одну операцию с обязательным qприсваиванием
Кортеж для примера был. Имелось ввиду class MatrixMul, MatrixPlus... Дальше можно извратиться с шаблонами построить на них синтаксический парсер и надеятся, что компилятор схлопнет все это в эффективный код
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
22.03.2016, 16:40
Цитата Сообщение от Evg Посмотреть сообщение
Но лишнее присваивание a=b таки будет исполнено (перед тем, как выполнить умножение)
Ну да, тогда извращаться.
Имхо - проще написать в С стиле, чем С++, но который без поллитры не разберешь.
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
22.03.2016, 16:43
Nosey, а ты зачем считаешь кол-во инструкций? Типа меньше инструкций - быстрее программа?

Цитата Сообщение от Evg Посмотреть сообщение
вся неэффективность растёт из
сказочных ограничений (типа С++98, с ООП и тп).

Цитата Сообщение от Evg Посмотреть сообщение
Потому что у многих в подсознании заложено в первую очередь то, что программа должна иметь как можно меньше букв в исходнике, а вовсе не потреблять как можно меньше количество тактов при исполнении
Что один, что другой подход - крайности какие-то.

Цитата Сообщение от Evg Посмотреть сообщение
которую получается написать эффективно только в "некультурном" стиле
А что такое "некультурный стиль" в С++?
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 16:48
ct0r, Как показывает практика, когда речь заходит о перемножении матриц - минимум тактов не крайность, а необходимость.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
22.03.2016, 16:57
Цитата Сообщение от avgoor Посмотреть сообщение
Как показывает практика, когда речь заходит о перемножении матриц - минимум тактов не крайность, а необходимость.
Я кэш-миссы даже считал, и префетчинг делал, чтоб их сократить. Да, если это узкое место, то приходится "вылизывать".
1
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 17:01
Цитата Сообщение от Kastaneda Посмотреть сообщение
Я кэш-миссы даже считал, и префетчинг делал, чтоб их сократить.
Аналогично.
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
22.03.2016, 17:05
Цитата Сообщение от avgoor Посмотреть сообщение
Как показывает практика, когда речь заходит о перемножении матриц - минимум тактов не крайность, а необходимость.
А причем тут практика и перемножение матриц? Там про подсознание.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
22.03.2016, 17:06
Цитата Сообщение от Evg Посмотреть сообщение
Зачем? Делать мне больше нечего, как тебя в чём-то переубеждать? За конкретным примером далеко ходить не надо, он написан в первом посте данной темы.
Потешно А ты его запускал свой конкретный пример?
Ну ладно, открывай ротик, закладываю :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "math/Math.h"
#include <iostream>
#include <vector>
 
const size_t c = 100000000;
 
ru::math::Matrix4 fcpp(const ru::math::Matrix4& mat1)
{
    ru::math::Matrix4 mat2 { 20, 30, 40 };
    return mat1 * mat2;
}
 
ru::math::Matrix4 mat1 { 10, 20, 30 };
ru::math::Matrix4 mat2 { 20, 30, 40 };
ru::math::Matrix4 mat3;
 
void fc(const ru::math::Matrix4* mat1)
{
    ru::math::Matrix4::operator_mul(&mat3, mat1, &mat2);
}
 
int main(void)
{
    std::vector<float> resVec;
    resVec.reserve(c);
    size_t i = c;
 
    clock_t startCpp = clock();
    while (--i)
    {
        resVec.push_back(fcpp(mat1).det());
    }
    clock_t endCpp = clock();
 
    std::cout << resVec.size() << " " << endCpp - startCpp << std::endl;
 
    resVec.clear();
    i = c;
 
    clock_t startC = clock();
    while (--i)
    {
        fc(&mat1);
        resVec.push_back(mat3.det());
    }
    clock_t endC = clock();
    std::cout << resVec.size() << " " << endC - startC << std::endl;
}
Реализация оператора умножения:
C++
1
2
3
4
5
6
            Matrix4 operator*(const Matrix4 &m) const
            {
                Matrix4 ret;
                operator_mul(&ret, this, &m);
                return ret;
            }
Вы только представьте сколько в Cpp реализации лишних копирований и присваиваний происходит, и все бесплатно, ах, эти новые квантовые ноутбуки.
Результаты :
99999999 3105052 - cpp
99999999 3098734 - c
И да, это расчёты честные, никаких компайлтайм расчётов нету.

Цитата Сообщение от ct0r Посмотреть сообщение
а ты зачем считаешь кол-во инструкций? Типа меньше инструкций - быстрее программа?
В данном случае - да, слишком уж большой разрыв для идентичных алгоритмов.
А вы считаете, что в данном случае меньшее количество инструкций хуже работают?
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
22.03.2016, 17:16
Цитата Сообщение от Nosey Посмотреть сообщение
В данном случае - да, слишком уж большой разрыв для идентичных алгоритмов.
А вы считаете, что в данном случае меньшее количество инструкций хуже работают?
Да я фиг знает. Мерить надо. Я не умею считать такты с учетом конвейеров и суперскалярности, с учетом зависимостей по данным, с учетом кол-ва обращений к памяти и кол-ва промахов кэша и тд и тп. Интуиция тут не помощник. Ну если кто-то умеет, то ок.
Компилятор, когда оптимизирует, на кол-во инструкций точно не смотрит.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.03.2016, 17:26  [ТС]
Цитата Сообщение от ct0r Посмотреть сообщение
А что такое "некультурный стиль" в С++?
Тот, который "в стиле языка Си". Т.е. в моей терминологии при написании программы на Си++ "культурно" это

C++
a = b * c;
не "культурно"

C
operator_mul (&a, &b, &c);
При написании "культурно" (т.е. в стиле Си++) программа выглядит красиво, но работает неэффективно

Добавлено через 9 минут
Цитата Сообщение от Nosey Посмотреть сообщение
Ну ладно, открывай ротик, закладываю
Мне не интересно смотреть на исходник, в котором используется какой-то непонятный самопальный Math.h, о содержании которого я должен догадываться. Засовывание результатов в вектор - это, насколько я понял, борьба с оптимизациями. Но тем не менее, этот процесс входит в замер. А если получится так, что на одну итерацию цикла приходится условно 10 тактов для умножения матрицы и 1000 тактов для засовывания в вектор (т.е. доля полезной нагрузки составляет 1% от общего времени), то такой замер ни о чём. Очевидно, ты об этом не задумывался, когда писал вектор, в который нужно будет засунуть 100 миллионов экземпляров и не можешь сказать, какую долю времени всего теста занимает менеджер памяти при работе с вектором. Так что твой пример я готов рассматривать только в варианте с полным исходником. Чтобы он изначально был рабочим, чтобы я его мог переписать с симетричными подходами "c" и "cpp" и с правильным построением замера

Правда я всё равно не понимаю, что ты мне продемонстрировать этим примером хочешь. Если хочешь продемонстрировать, что ненужные копирования занимают всего 1% (2%, 3%, не суть) от времени исполнения, то мне это вовсе не интересно. Если для выполнения какой-то задачи код должен быть быстрым, то борьба идёт за каждый процент времени исполнения
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
22.03.2016, 17:28
Evg, ну ООП в С++ тогда тоже некультурно, потому что в стиле Smalltalk. А перегрузка операторов - потому что в стиле ALGOL.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.03.2016, 17:29  [ТС]
Цитата Сообщение от avgoor Посмотреть сообщение
Имелось ввиду class MatrixMul, MatrixPlus... Дальше можно извратиться с шаблонами построить на них синтаксический парсер и надеятся, что компилятор схлопнет все это в эффективный код
Если рассматривать вариант с извращениями, то написание функции с тремя аргументами выглядит самым простым и эффективным решением. Я плохо знаю Си++, потому и спросил. Я думал, что можно написать реализацию матриц так, чтобы можно было писать "a = b * c" и иметь при этом эффективный код
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
22.03.2016, 17:43
Цитата Сообщение от Evg Посмотреть сообщение
чтобы можно было писать "a = b * c" и иметь при этом эффективный код
...
Цитата Сообщение от avgoor Посмотреть сообщение
Зависит много от чего. Например: размерность матрицы - это поле класса или параметр шаблона? Может это вообще разреженые матрицы итд.
Теоретически можно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.03.2016, 17:43
Помогаю со студенческими работами здесь

Какое значение получит переменная p при выполнении следующего оператора присваивания?
var p: set of 0..9; i, j: integer; Если i=2 и j=5, то какое значение получит переменная p при выполнении следующего оператора...

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

Ошибка при реализации перегрузки оператора <<
Добрый день. Прошу помощи. Имеется такой класc. class DList { ... public: ... void Save(std::ofstream &amp;b_out); //...

Ошибка в вводе данных из HTML и переносе их в JavaScript, при выполнении оператора IF или оператора swithc
доброго времени суток, при выполнении одной учебной задачи столкнулся с проблемой: при введении любого значения в поле, код выдает только...

Переопределение оператора присваивания
Имеется такой простой класс: class TClass { private: float* A; int N; public: TClass(int _N) ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru