Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.68/22: Рейтинг темы: голосов - 22, средняя оценка - 4.68
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13

Какова польза лямбда выражений

17.03.2014, 13:05. Показов 4524. Ответов 31
Метки нет (Все метки)

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

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * main.cpp
 *
 *  Created on: 31 янв. 2014 г.
 *      Author: volodja
 */
 
 
 
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <string>
 
 
#include "stopwatch.h"
 
 
using namespace std;
 
 
timeval getCurrentTime() {
    timeval current_time;
    gettimeofday(&current_time, NULL);
    return  current_time;
}
 
 
uint64_t getElapsedMicrosecond(const timeval &stopwatch_time) {
    timeval current_time = getCurrentTime();
    return (current_time.tv_sec - stopwatch_time.tv_sec) * 1000000 + current_time.tv_usec - stopwatch_time.tv_usec;
}
 
 
vector<char> testCopy() {
    vector<char>    result;
    char            ch = 0;
 
    for (size_t i = 0; i < 10; i++) {
        ch++;
        result.push_back(ch);
    }
 
    return result;
}
 
 
vector<char>&& testMove() {
    vector<char>    result;
    char            ch = 0;
 
    for (size_t i = 0; i < 10; i++) {
        ch++;
        result.push_back(ch);
    }
 
    return move(result);
}
 
 
void testMoveVsCopy() {
    timeval         stopwatch_time;
    const size_t    count = 1000000;
    vector<char>    v;
 
    {
        cout << "copy: " << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            v.push_back(testCopy()[i % 100]);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "copy lambda: " << endl;
        stopwatch_time = getCurrentTime();
        size_t i = 0;
        generate_n(back_inserter(v), count,
            [&i]() -> char {
                i++;
                return testCopy()[i % 100];
            }
        );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "move: " << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            v.push_back(testMove()[i % 100]);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "move lambda: " << endl;
        stopwatch_time = getCurrentTime();
        size_t i = 0;
        generate_n(back_inserter(v), count,
            [&i]() -> char {
                i++;
                return testMove()[i % 100];
            }
        );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
//void executeLambda([](const int &i) -> double) {
//
//}
 
 
void testLambda() {
    int a = 1, b = 2;
    cout << "b = " << b << endl;
    [=, &b]{
        b = b + a;
    }();
    cout << "b = " << b << endl;
 
}
 
 
int main() {
    testMoveVsCopy();
 
    testLambda();
 
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.03.2014, 13:05
Ответы с готовыми решениями:

Использование лямбда-выражений в STL
Где dictionary - вектор, word1,word2 - string слова for(size_t i = 0; i &lt; word2.length(); ++i) { word1 = *find_if ...

Поддержка лямбда-выражений
public interface MyNameIn { int GetValue(); } class LambdaDemo { public static void main(String args) { MyNameIn myInter; ...

Дебаггинг анонимных методов и лямбда-выражений
Добрый вечер. Написал свой первый более-менее серьезный и полезный проект на C# и уперся в дебаггинг. По опыту микроконтроллеров знаю, что...

31
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 13:09
А может нужно научиться готовить их?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
17.03.2014, 13:25
Фраза
Цитата Сообщение от volodja- Посмотреть сообщение
лямбда выражения медленней простых циклов
звучит как "удобрения медленнее лопаты". Абсурд не правда ли?
Сами по себе лямбда выражения - это синтаксический сахар для функторов. В С++ до этого не существовало способа сделать анонимный функтор, теперь такой способ есть, + некоторые плюшки (вроде захвата переменных). То, что ты там в своем примере заюзал стандартные алгоритмы с таким функтором и получил просадку производительности по сравнению с голым циклом, вообще никак лямбды не характеризует. Характеризует только то, что тест некорректный.
1
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 13:33  [ТС]
в чем не корректность теста ?
И что тогда лучше использовать в местах с простыми циклами, лямбда или циклы(итераторы) ?
Еще так к месту, конструкторы перемещения дают очень небольшой прирост производительности (в 1,04873245 раза).
Использовал самые простые конструкции, может быть лямбда можно как-то лучше приготовить ?
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 13:35
Цитата Сообщение от volodja- Посмотреть сообщение
дают очень небольшой прирост производительности
ну попробуйте скопировать и переместить вектор из 100000000 объектов
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
17.03.2014, 13:40
Цитата Сообщение от volodja- Посмотреть сообщение
в чем не корректность теста ?
В том, что ты сравниваешь совершенно разные подходы к решению задачи. Выбрав при этом условия задачи такими, что подход с голыми циклами оказывается быстрее. Для корректности нужно было сравнивать лямбды с обычными С++ функторами (которые классы).

Цитата Сообщение от volodja- Посмотреть сообщение
И что тогда лучше использовать в местах с простыми циклами
От задачи зависит. И от целей. Озвучь конкретную задачу, будем ее рассматривать.
И еще раз скажу, лямбды - это функторы (то есть функциональные объекты, то есть объекты, которые ведут себя как функции). Ее совсем не обязательно в цикл пихать.

Цитата Сообщение от volodja- Посмотреть сообщение
конструкторы перемещения дают очень небольшой прирост производительности (в 1,04873245 раза).
А это зависит от характера данных. Нельзя так просто в общем случае утверждать.
0
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 13:41  [ТС]
А цикл быстрее лямбда быстрее в 1,240681149 раза (видимо за счет создания временной структуры в каждой итерации).
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
17.03.2014, 13:43
Цитата Сообщение от volodja- Посмотреть сообщение
А цикл быстрее лямбда
Не цикл быстрее лямбды, а цикл быстрее подхода с использованием стандартного алгоритма в этой конкретной ситуации.
1
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 13:54  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
А это зависит от характера данных. Нельзя так просто в общем случае утверждать.
В данном тесте я проверял только скорость передачи данных из локальной области видимости во внешнюю область видимости (фактически скорость return), данные не суть важно какие, просто небольшой массив байт. Не думаю что из безымянных структур можно создавать какие-то сложные конструкции, по этому предполагаю что лямда и подразумевает использование в небольших локальных конструкциях с stl.algorithm.

Добавлено через 5 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Для корректности нужно было сравнивать лямбды с обычными С++ функторами (которые классы).
Смысла нет, т.к. это одно и тоже только по разному записано, т.е. лямда при компиляции преобразуется в класс.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 14:02
Цитата Сообщение от volodja- Посмотреть сообщение
данные не суть важно какие
просто для примера:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct TEST {
   TEST ( ) {
      std::cout << "create test object" << std::endl ;
   }
   TEST ( const TEST & ) {
      std::cout << "copy test object" << std::endl ;
   }
   ~TEST ( ) {
      std::cout << "delete test object" << std::endl ;
   }
} ;
 
 
int main () {
   std::vector<TEST> vec1(5) ;
   std::cout << "BEGIN\nCopy:\n" ;
   std::vector<TEST> vec2 (vec1);
   std::cout << "Move:\n" ;
   std::vector<TEST> vec3 (std::move ( vec1 ) );
   std::cout << "END" << std::endl ;
}
Вы вообще сравниваете теплое с мягким
1
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 14:21  [ТС]
В моем примере оптимизация компилятора почти что уравнивает по скорости конструктор копирования и перемещения при возврате результата, по этому разница в скорости различима только для циклов и лямбда.
Вывод в консоль такой (gcc 4.7.3):

copy:
182104
copy lambda:
225933
move:
173642
move lambda:
222386
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 14:36
Цитата Сообщение от volodja- Посмотреть сообщение
В моем примере оптимизация компилятора почти что уравнивает по скорости конструктор копирования и перемещения при возврате результата
В Вашем примере большая часть теста не корректна
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 14:55
Чуть поменял, чтобы не было автоматических переменных в некоторых местах, которые будут не копироваться, а перемещаться
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <string>
 
 
 
using namespace std;
 
 
timeval getCurrentTime() {
    timeval current_time;
    gettimeofday(&current_time, NULL);
    return  current_time;
}
 
 
uint64_t getElapsedMicrosecond(const timeval &stopwatch_time) {
    timeval current_time = getCurrentTime();
    return (current_time.tv_sec - stopwatch_time.tv_sec) * 1000000 + current_time.tv_usec - stopwatch_time.tv_usec;
}
 
 
vector<char> testCopy( vector<char> & result ) {
 
    char            ch = 0;
 
    for (size_t i = 0; i < 100000; i++) {
        ch++;
        result.push_back(ch);
    }
 
    return result;
}
 
 
vector<char> testMove(vector<char>  &result) {
    char            ch = 0;
 
    for (size_t i = 0; i < 10000; i++) {
        ch++;
        result.push_back(ch);
    }
 
    return move(result);
}
 
 
void testMoveVsCopy() {
    timeval         stopwatch_time;
    const size_t    count = 1000;
    vector<char>    v;
 
    {vector<char>    v2;
        cout << "copy: " << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            v.push_back(testCopy(v2)[0]);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {vector<char>    v2;
        cout << "copy lambda: " << endl;
        stopwatch_time = getCurrentTime();
        size_t i = 0;
        generate_n(back_inserter(v), count,
            [&i,&v2]() -> char {
                i++;
                return testCopy(v2)[0];
            }
        );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {vector<char>    v2;
        cout << "move: " << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            v.push_back(testMove(v2)[0]);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {vector<char>    v2;
        cout << "move lambda: " << endl;
        stopwatch_time = getCurrentTime();
        size_t i = 0;
        generate_n(back_inserter(v), count,
            [&i,&v2]() -> char {
                i++;
                return testMove(v2)[0];
            }
        );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
//void executeLambda([](const int &i) -> double) {
//
//}
 
 
void testLambda() {
    int a = 1, b = 2;
    cout << "b = " << b << endl;
    [=, &b]{
        b = b + a;
    }();
    cout << "b = " << b << endl;
 
}
 
 
int main() {
    testMoveVsCopy();
 
    testLambda();
 
    return 0;
}
Результаты:
1
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 14:58
Еще вопросы по эффективности перемещения имеются?
0
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 15:50  [ТС]
в общем разъяснил ситуацию лямбда, результат прямо противоположный:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * main.cpp
 *
 *  Created on: 31 янв. 2014 г.
 *      Author: volodja
 */
 
 
 
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <string>
 
 
using namespace std;
 
 
timeval getCurrentTime() {
    timeval current_time;
    gettimeofday(&current_time, NULL);
    return  current_time;
}
 
 
uint64_t getElapsedMicrosecond(const timeval &stopwatch_time) {
    timeval current_time = getCurrentTime();
    return (current_time.tv_sec - stopwatch_time.tv_sec) * 1000000 + current_time.tv_usec - stopwatch_time.tv_usec;
}
 
 
void testLambdaVsFor() {
    const size_t    count = 100000000;
    vector<char>    data;
    timeval         stopwatch_time;
    char            ch = 0;
 
    cout << "data pushback " << endl;
    {
        cout << "  lambda:" << endl;
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), [&ch]() {return ch++;} );
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "  lambda back_inserter:" << endl;
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, [&ch]() {return ch++;} );
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "  for counter:" << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            data.push_back(ch++);
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "data modify" << endl;
    {
        cout << "  lambda:" << endl;
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](char &ch) {ch++;} );
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "  for iterator:" << endl;
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            (*i)++;
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "  for counter:" << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i]++;
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
}
 
 
int main() {
    testLambdaVsFor();
 
    return 0;
}
вывод:
data pushback
lambda:
53000
lambda back_inserter:
194452
for counter:
220521
data modify
lambda:
10275
for iterator:
61350
for counter:
120558

Добавлено через 6 минут
Цитата Сообщение от Croessmah Посмотреть сообщение
Чуть поменял, чтобы не было автоматических переменных в некоторых местах, которые будут не копироваться, а перемещаться
Скомпилено с оптимизацией без дебага ?
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 15:53
Цитата Сообщение от volodja- Посмотреть сообщение
Скомпилено с оптимизацией без дебага ?
Release.
У Вас вектора были локальными и при возврате они перемещались, а не копировались, а в testMove, вы вообще ссылку возвращали
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
17.03.2014, 15:54
volodja-, в одном случае для вектора сразу сделан resize, в другом - вставка back_inserter'ом, и, как следствие, перевыделения памяти и копирования объектов. В общем, я не понимаю что вы пытаетесь измерить.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 16:04
Цитата Сообщение от 0x10 Посмотреть сообщение
и, как следствие, перевыделения памяти и копирования объектов.
ну перевыделения врядли будут, ибо data.clear() лишь очищает вектор, но не освобождает память и выделенного куска хватит для следующего теста
Цитата Сообщение от 0x10 Посмотреть сообщение
в одном случае для вектора сразу сделан resize, в другом - вставка back_inserter'ом
угу, поэтому
Цитата Сообщение от 0x10 Посмотреть сообщение
В общем, я не понимаю что вы пытаетесь измерить.
ответ - теплое с мягким. Сравнивает изменение элементов(generate) с их вставкой(push_back)
0
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 16:05  [ТС]
Согласен, пункт lambda: 53000 можно отбросить, не нашел пока способа вызывать push_back из лямбда. Но пункты в data modify выглядят достоверно.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
17.03.2014, 16:09
Цитата Сообщение от volodja- Посмотреть сообщение
Но пункты в data modify выглядят достоверно.
а если так?
C++
1
2
3
4
5
        cout << "  for counter:" << endl;
        stopwatch_time = getCurrentTime();
        for (char * p = data.data(), * pend = p+data.size(); p<pend; ++p)
            (*p)++;
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.03.2014, 16:09
Помогаю со студенческими работами здесь

Переопределить метод ToString() на основе лямбда-выражений
Хай. Нужно переопределить метод ToString() на основе лямбда-выражений. Подскажите, пожалуйста, как это сделать, а то не понятно про эти...

В чем разница лямбда-выражений и анонимных методов?
В книге Шидта приводится два способа создания анонимных функций: 1) с использованием ключевого слова &quot;delegate&quot;; 2) с...

Программа с использованием делегатов, анонимных методов и лямбда-выражений
помогите с кодом программы. условие программы: с использованием делегата следующего вида delegate int имя (int a, int b). создать...

Реализовать с применением функционалов и лямбда-выражений следующую функцию
Здравстуйте, помогите решить задачку: &quot;Реализовать с применением функционалов и лямбда-выражений следующую функцию: для исходного...

Реализовать заданные функции при помощи лямбда-выражений
Здравствуйте, помогите, пожалуйста реализовать следующие функции при помощи лямбда выражений: def square(x): return x * x ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
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 . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru