Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
#1

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

17.03.2014, 13:05. Просмотров 1563. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.03.2014, 13:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Какова польза лямбда выражений (C++):

Написать парсер математических выражений с функцией упрощения этих выражений - C++
Люди, здравствуйте. Есть такая задача: написать упроститель выражений. На вход подается строка вида &quot;a*b+a*c&quot;, являющаяся корректным...

Отладчики - какая от них польза и как ими правильно пользоваться? - C++
Какую пользу несут отладчики и как ими правильно пользоваться? Нет, как его запустить я себе представляю (благо иде помогает), но что я...

Рекурсивная лямбда - C++
можно ли в лямбде сделать рекурсию? как получить имя безымянной функции? this не пашет...

Лямбда функции - C++
Всем добрый вечер! Пытаюсь ознакомиться поближе с лямбда функциями и уже возникли трудности... Просмотрела пару публикаций на эту тему и...

лямбда функция - C++
привет всем! не понимаю в чем ошибка...вот код vector&lt;string&gt; tmp_count; list&lt;string&gt; tmp_result = str; for(auto i =...

Лямбда функции - C++
Помогите пожалуйста. Написать программу демонстрирующую лямбда функцию на с++. желательно с комментариями, а то я в этом совсем ничего не...

31
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
17.03.2014, 15:53 #16
Цитата Сообщение от volodja- Посмотреть сообщение
Скомпилено с оптимизацией без дебага ?
Release.
У Вас вектора были локальными и при возврате они перемещались, а не копировались, а в testMove, вы вообще ссылку возвращали
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,093
17.03.2014, 15:54 #17
volodja-, в одном случае для вектора сразу сделан resize, в другом - вставка back_inserter'ом, и, как следствие, перевыделения памяти и копирования объектов. В общем, я не понимаю что вы пытаетесь измерить.
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
17.03.2014, 16:04 #18
Цитата Сообщение от 0x10 Посмотреть сообщение
и, как следствие, перевыделения памяти и копирования объектов.
ну перевыделения врядли будут, ибо data.clear() лишь очищает вектор, но не освобождает память и выделенного куска хватит для следующего теста
Цитата Сообщение от 0x10 Посмотреть сообщение
в одном случае для вектора сразу сделан resize, в другом - вставка back_inserter'ом
угу, поэтому
Цитата Сообщение от 0x10 Посмотреть сообщение
В общем, я не понимаю что вы пытаетесь измерить.
ответ - теплое с мягким. Сравнивает изменение элементов(generate) с их вставкой(push_back)
0
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 16:05  [ТС] #19
Согласен, пункт lambda: 53000 можно отбросить, не нашел пока способа вызывать push_back из лямбда. Но пункты в data modify выглядят достоверно.
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
17.03.2014, 16:09 #20
Цитата Сообщение от 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
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 17:59  [ТС] #21
а теперь так:
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * 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 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;
    }
}
 
 
class A {
public:
    A()
    :
        i(0)
    {
    }
 
   ~A() {
    }
 
    void increase() {
        i++;
    }
 
private:
    int i;
};
 
 
void testLambdaVsFor() {
    const size_t    count = 100000000;
    vector<A>       data;
    timeval         stopwatch_time;
 
    cout << "data pushback " << endl;
    {
        cout << "  lambda:" << endl;
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), []() {return A();} );
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "  lambda back_inserter:" << endl;
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, []() {return A();} );
        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(A());
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "data modify" << endl;
    {
        cout << "  lambda:" << endl;
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](A &a) {a.increase();} );
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "  for iterator:" << endl;
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            i->increase();
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "  for counter:" << endl;
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i].increase();
        cout << "  " << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
int main() {
    testLambdaVsFor();
 
    return 0;
}

здесь у меня сомнения на счет
C++
1
std::for_each(data.begin(), data.end(), [](A &a) {a.increase();} );
того что "а" изменяется по ссылке

вывод:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
data pushback 
  lambda:
  204060
  lambda back_inserter:
  146439
  for counter:
  195790
data modify
  lambda:
  41585
  for iterator:
  40639
  for counter:
  40518
Добавлено через 1 час 21 минуту
взгляните еще раз на тест, все ли верно, добавил еще конструкторы перемещения:

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * 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;
}
 
 
class A {
public:
    A()
    :
        i(0)
    {
    }
 
   ~A() {
    }
 
    void increase() {
        i++;
    }
 
private:
    int i;
};
 
 
void testLambdaVsForPointer() {
    const size_t    count = 10000000;
    vector<A*>      data;
    timeval         stopwatch_time;
 
    cout << "test lambda vs for dynamic objects:" << endl;
    cout << "  data pushback " << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), []() -> A* {return new A;} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
    data.clear();
 
    {
        cout << "    lambda back_inserter:         ";
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, []() -> A* {return new A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
    data.clear();
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            data.push_back(new A());
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "  data modify" << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](A *a) {a->increase();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for iterator:                 ";
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            (*i)->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i]->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
}
 
 
void testLambdaVsFor() {
    const size_t    count = 10000000;
    vector<A>       data;
    timeval         stopwatch_time;
 
    cout << "test lambda vs for static objects:" << endl;
    cout << "  data pushback " << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), []() {return A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "    lambda back_inserter:         ";
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, []() {return A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            data.push_back(A());
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "  data modify" << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](A &a) {a.increase();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for iterator:                 ";
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            i->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i].increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
vector<A> copy(const size_t &count) {
    vector<A>   data(count);
    return      data;
}
 
 
vector<A> move(const size_t &count) {
    vector<A>   data(count);
    return      move(data);
}
 
 
void testMoveVsCopy() {
    cout << "test move vs copy:" << endl;
 
    const size_t    size    = 10;
    const uint      count   = 100000000;
    vector<A>       data(size);
    timeval         stopwatch_time;
 
    {
        cout << "    copy:                         ";
        stopwatch_time = getCurrentTime();
        for (uint i = 0; i < count; i++)
            data = copy(size);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
 
    {
        cout << "    move:                         ";
        stopwatch_time = getCurrentTime();
        for (uint i = 0; i < count; i++)
            data = move(size);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
int main() {
    testLambdaVsForPointer();
    testLambdaVsFor();
    testMoveVsCopy();
 
    return 0;
}

вывод:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
test lambda vs for dynamic objects:
  data pushback 
    lambda:                       357995
    lambda back_inserter:         179733
    for counter:                  181910
  data modify
    lambda:                       36126
    for iterator:                 36224
    for counter:                  36146
test lambda vs for static objects:
  data pushback 
    lambda:                       49147
    lambda back_inserter:         17607
    for counter:                  20895
  data modify
    lambda:                       4429
    for iterator:                 4041
    for counter:                  4040
test move vs copy:
    copy:                         3108588
    move:                         3115485
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
17.03.2014, 18:04 #22
C++
1
2
3
4
vector<A> copy(const size_t &count) {
    vector<A>   data(count);
    return      data;//<-- кто Вам сказал что здесь будет копирование?
}
0
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 18:44  [ТС] #23
поменял код на
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const size_t    size    = 10;
vector<A> input_data(size);
 
 
vector<A> copy(const size_t &count) {
    vector<A> result;
    result.assign(input_data.begin(), input_data.end());
    return result;
}
 
 
vector<A> move(const size_t &count) {
    return move(input_data);
}

стало:
Bash
1
2
3
test move vs copy:
    copy:                         4202579
    move:                         182200
но здесь мне пришлось явно указать копирование

Цитата Сообщение от Croessmah Посмотреть сообщение
return * * *data;//<-- кто Вам сказал что здесь будет копирование?
по идее здесь компилятор оптимизирует копирование временного объекта в перемещение, т.е. move не обязательно писать

Добавлено через 7 минут
теперь точно копирование, окончательный код:

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * 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;
}
 
 
class A {
public:
    A()
    :
        i(0)
    {
    }
 
   ~A() {
    }
 
    void increase() {
        i++;
    }
 
private:
    int i;
};
 
 
void testLambdaVsForPointer() {
    const size_t    count = 10000000;
    vector<A*>      data;
    timeval         stopwatch_time;
 
    cout << "test lambda vs for dynamic objects:" << endl;
    cout << "  data pushback " << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), []() -> A* {return new A;} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
    data.clear();
 
    {
        cout << "    lambda back_inserter:         ";
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, []() -> A* {return new A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
    data.clear();
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            data.push_back(new A());
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "  data modify" << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](A *a) {a->increase();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for iterator:                 ";
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            (*i)->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i]->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    std::for_each(data.begin(), data.end(), [](A *a) {delete a;} );
}
 
 
void testLambdaVsFor() {
    const size_t    count = 10000000;
    vector<A>       data;
    timeval         stopwatch_time;
 
    cout << "test lambda vs for static objects:" << endl;
    cout << "  data pushback " << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        data.resize(count);
        generate(data.begin(), data.end(), []() {return A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "    lambda back_inserter:         ";
        stopwatch_time = getCurrentTime();
        generate_n(back_inserter(data), count, []() {return A();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    data.clear();
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < count; i++)
            data.push_back(A());
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    cout << "  data modify" << endl;
    {
        cout << "    lambda:                       ";
        stopwatch_time = getCurrentTime();
        std::for_each(data.begin(), data.end(), [](A &a) {a.increase();} );
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for iterator:                 ";
        stopwatch_time = getCurrentTime();
        for (auto i = data.begin(); i != data.end(); i++)
            i->increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
    {
        cout << "    for counter:                  ";
        stopwatch_time = getCurrentTime();
        for (size_t i = 0; i < data.size(); i++)
            data[i].increase();
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
const size_t    size    = 10;
vector<A> input_data(size);
 
 
vector<A> copy(const size_t &count) {
    return input_data;
}
 
 
vector<A> move(const size_t &count) {
    return move(input_data);
}
 
 
void testMoveVsCopy() {
    cout << "test move vs copy:" << endl;
 
    const uint      count   = 100000000;
    vector<A>       data(size);
    timeval         stopwatch_time;
 
    {
        cout << "    copy:                         ";
        stopwatch_time = getCurrentTime();
        for (uint i = 0; i < count; i++)
            data = copy(size);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
 
 
    {
        cout << "    move:                         ";
        stopwatch_time = getCurrentTime();
        for (uint i = 0; i < count; i++)
            data = move(size);
        cout << getElapsedMicrosecond(stopwatch_time) << endl;
    }
}
 
 
int main() {
    testLambdaVsForPointer();
    testLambdaVsFor();
    testMoveVsCopy();
 
    return 0;
}

вывод:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
test "lambda" vs "for", dynamic objects:
  data pushback 
    lambda:                       350438
    lambda back_inserter:         171635
    for counter:                  172581
  data modify
    lambda:                       35920
    for iterator:                 35974
    for counter:                  36039
test "lambda" vs "for", static objects:
  data pushback 
    lambda:                       50632
    lambda back_inserter:         18197
    for counter:                  20828
  data modify
    lambda:                       4016
    for iterator:                 4076
    for counter:                  4039
test constructor "move" vs "copy":
    copy:                         3562513
    move:                         177599

временные локальные переменные в функциях при возврате значения оптимизируются в место конструктора копирования используется конструктор перемещения.

Добавлено через 5 минут
Ну и, наконец, тест показывает что все три способа перебора массива примерно одинаковы по скорости, тогда в чем сахар синтаксиса лямбда выражений ?
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
17.03.2014, 19:02 #24
Цитата Сообщение от volodja- Посмотреть сообщение
одинаковы по скорости
Цитата Сообщение от volodja- Посмотреть сообщение
сахар синтаксиса лямбда выражений
Откуда такая тяга сравнивать несравниваемое?
Сахар в том, что не надо писать отдельный класс для функтора. Если нужен захват локальных переменных, то не надо заботиться о "протаскивании" их в этот класс. И не надо думать о том, что имя очередного написанного функтора совпадет с одним из уже существующих. Это и называется синтаксический сахар, проще говоря, когда надо писать меньше кода [по сравнению с аналогичным вариантом].
1
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
17.03.2014, 19:17  [ТС] #25
данный исходник показывает что лямбда даже немножко более громоздки чем циклы
0
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
17.03.2014, 19:26 #26
Цитата Сообщение от volodja- Посмотреть сообщение
данный исходник показывает что лямбда даже немножко более громоздки чем циклы
a + b короче чем Ваш цикл, пользуйтесь!
Можете еще циклы с диррективами препроцессора сравнить или принтер с клавиатурой - а че, оба же печатают
0
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
18.03.2014, 08:30  [ТС] #27
тем не менее вопрос по лямбда остается открытым ...
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
18.03.2014, 08:42 #28
volodja-, какой вопрос-то?
Нет никакого смысла сравнивать функторы с голыми циклами в общем случае. Если у тебя такая задача, где подходит обычный перебор в цикле, то надо использовать его. Если у тебя задача, где нужно абстрагироваться от конкретного действия, то лучше подходят лямбды. Можно сравнивать только так: что лучше решает конкретную задачу. Просто всегда по-умолчанию фигачить все в теле цикла, или просто всегда по-умолчанию фигачить алгоритмы с лямбдами - неправильно.
И как уже говорилось не раз, лямбды это функторы, то есть их используют не только для перебора чего-то в цикле. У них применение гораздо более широкое. Исходя из этого, вопрос "что лучше циклы или лямбды" не имеет ответа в такой формулировке.
0
volodja-
0 / 0 / 0
Регистрация: 17.03.2014
Сообщений: 13
18.03.2014, 10:27  [ТС] #29
можете привести пример когда уместно использовать лямбда и не уместно циклы и наоборот ?
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,093
18.03.2014, 10:44 #30
Цитата Сообщение от volodja- Посмотреть сообщение
можете привести пример когда уместно использовать лямбда и не уместно циклы и наоборот ?
Вам тут в каждом посте одно и то же повторяют: эти вещи не являются взаимозаменяемыми, поскольку они вообще про разное.
0
18.03.2014, 10:44
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.03.2014, 10:44
Привет! Вот еще темы с ответами:

Лямбда выражения - C++
Здрасьте) вопрос по новому стандарту, в который ввели лямбда-выражения. создаю класс, у которого есть поле data, типа map. map...

Передача лямбда в функции - C++
В чем смысл передачи лямбда выражения функции?auto square = (int x) { return x * x; }; std::cout &lt;&lt; square(16) &lt;&lt; std::endl;илиclass Foo ...

Лямбда не допускает auto - C++
Всем привет! Имеем код: #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; #include &lt;numeric&gt; int...

Лямбда, список захвата - C++
Есть ли возможность поместить в список захвата лямбды, которая находится в методе, переменную член этого класса? Точнее как это лучше...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru