С++ в относительно новых стандартах
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
С++ в относительно новых стандартах
Почему такое хитрое название темы?
Потому что:
- меня эти конструкции интересуют в практическом применении, в проекте...
- интересуют возможности C++11, которые расширены и поправлены (не существенно) C++14 ... а вот C++17 мне "до фени", поскольку по моим представлениям это просто адаптация C++ под нужды живущих в мире Windows.
Интересует, главным образом, новые выразительные средства из области STL, функторов, алгоритмов, лямбда-функций etc,
P.S. Т.е. эта тема, в отличие от всего остального форума - заметки (этюды) по мотивам моей текущей практической работы в весьма крупном разработческом (и сопроводительном - дополнениями) проекте ... заметки по конкретным задачам, которые возникнут в ходе этой работы.
Множество коротких примеров я уже использовал в своём длинном тексте: Начала STL и контейнеры C++ ... особенно применительно не к контейнерам, а к классическим регулярным массивам C (это писалось в годы 2015-16, когда ещё про C++17 никто, слава Богу, и не слышал).
P.S. Я даже прикреплю, пожалуй, этот текст (в самой свежей и полной редакции) сюда, чтобы он у меня был под рукой.
Потому что:
- меня эти конструкции интересуют в практическом применении, в проекте...
- интересуют возможности C++11, которые расширены и поправлены (не существенно) C++14 ... а вот C++17 мне "до фени", поскольку по моим представлениям это просто адаптация C++ под нужды живущих в мире Windows.
Интересует, главным образом, новые выразительные средства из области STL, функторов, алгоритмов, лямбда-функций etc,
P.S. Т.е. эта тема, в отличие от всего остального форума - заметки (этюды) по мотивам моей текущей практической работы в весьма крупном разработческом (и сопроводительном - дополнениями) проекте ... заметки по конкретным задачам, которые возникнут в ходе этой работы.
Множество коротких примеров я уже использовал в своём длинном тексте: Начала STL и контейнеры C++ ... особенно применительно не к контейнерам, а к классическим регулярным массивам C (это писалось в годы 2015-16, когда ещё про C++17 никто, слава Богу, и не слышал).
P.S. Я даже прикреплю, пожалуй, этот текст (в самой свежей и полной редакции) сюда, чтобы он у меня был под рукой.
- Вложения
-
- AllSTL_14a.odt
- (313.7 КБ) 72 скачивания
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Реальная подзадача: определить "принтебельнсть" ASCII символьной строки (желательно самым коротким способом), в смысле POSIX функции isprint().
Тестовая задача:
Код: Выделить всё
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const char* stest[] = {
"asdf0987\t",
"zf""\xAA""bc0de",
"1234567890",
"#$@__12345",
"abc""\xFF",
"ZXFfxz",
"строка"
};
int main( int argc, char *argv[] ) {
for (int n = 0; n < (int)(sizeof(stest) / sizeof(stest[0])); n++) {
const char *str = stest[n];
const int len = strlen(stest[n]);
cout << "<" << str << "> "
<< " | " << (std::all_of(str, str + len, [](char p)->bool{ return ( isprint( p ) != 0 ); }) ? "true" : "false" )
<< endl;
}
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ g++ printable.cc -o printable
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./printable
<asdf0987 > | false
<zf�bc0de> | false
<1234567890> | true
<#$@__12345> | true
<abc�> | false
<ZXFfxz> | true
<строка> | false
- Вложения
-
- printable.cc
- (872 байт) 64 скачивания
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Очень интересная статья про лямда-функции, особенно в части автоматического выведения типов C++14: Лямбда-выражения (анонимные функции) в С++
Обновл. 8 Сен 2020
Мы можем улучшить читабельность кода следующим образом:Код: Выделить всё
// Хорошо: Мы можем хранить лямбду в именованной переменной и передавать её в функцию в качестве параметра auto isEven{ [](int i) { return ((i % 2) == 0); } };
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Вопрос: что дают sizeof() относительно описаний типов/классов, и имплементированных объектов этих классов?
Ничего военного в вопросе нет ... но он возникает (и возник в реальном проекте) при сериализации объектов, когда объект нужно передать через среду передачи (сеть и т.д.) в потоке, но на то конце восстановить в неизменном виде.
Тут, как раз, нет ничего неожиданного...
Но такие неожиданности попадаются ... просто пока я их не могу сформулировать в локальных примерах.
Если у кого найдётся нетривиальный пример при сериализации - давай его сюда!
Ничего военного в вопросе нет ... но он возникает (и возник в реальном проекте) при сериализации объектов, когда объект нужно передать через среду передачи (сеть и т.д.) в потоке, но на то конце восстановить в неизменном виде.
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ cat sizeof.cc
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
struct xxxx
{
const static uint16_t p1;
static int p2, p3;
uint8_t data[ 10 ];
};
template <class T> class TClass
{
T t1, t2;
};
struct zz
{
uint8_t d1, d2, d3, d4;
};
struct zzzz
{
uint8_t data[ 10 ];
};
struct nnnn
{
static long int n;
vector<int> data;
nnnn( void )
{
data.resize( n );
}
};
long int nnnn::n = 3;
int main( int argc, char *argv[] ) {
xxxx yyyy;
string s;
TClass<zzzz> uuuu;
cout << sizeof( xxxx ) << endl
<< sizeof( yyyy ) << endl
<< sizeof( TClass<zzzz> ) << endl
<< sizeof( uuuu ) << endl
<< sizeof( s ) << endl
<< sizeof( TClass<string> ) << endl
<< sizeof( nnnn ) << endl;
nnnn N3;
cout << sizeof( N3 ) << endl;
nnnn::n = 300;
nnnn N300;
cout << sizeof( N300 ) << endl;
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ g++ sizeof.cc -o sizeof
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./sizeof
10
10
20
20
32
64
24
24
24
Если у кого найдётся нетривиальный пример при сериализации - давай его сюда!
- Вложения
-
- sizeof.cc
- (947 байт) 65 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Ещё возникла подобная задача: в последовательности элементов (вектор, массив в стиле C, любой контейнер, ...) проверить, что некоторый диапазон последовательных элементов все попадают под какое-то условие (чётные, нечётные, положительные, отрицательные ... простые числа, литеры русского алфавита ... всё что угодно!).
P.S. почему next() и prev() а не +3 и -4? потому что это будет работать с любыми контейнерами, а не только с векторами.
Код: Выделить всё
#include <iostream> // std::cout
#include <iterator> // std::next std::next
#include <algorithm> // std::all_of
#include <array> // std::array
using namespace std;
int main( int argc, char *argv[] ) {
array<int,8> arr1 = {3,5,7,11,13,17,19,23};
if ( all_of(arr1.begin(), arr1.end(), [](int i){return i%2;}) )
cout << "All the elements are odd numbers." << endl;
array<int,12> arr2 = {1,3,5,2,2,4,6,8,10,12,10,8};
if (all_of(next(arr2.begin(), 3), arr2.end(), [](int i)->bool{return !(i%2);}))
cout << "The elements begin from 4 are even numbers.\n";
int arr3[] = {1,3,5,2,2,4,6,8,10,12,10,8};
if (all_of(arr3 + 3, arr3 + sizeof(arr3) / sizeof(arr3[0]) - 1, [](int i)->bool{return !( i%2 );}))
cout << "The elements begin from 4 are even numbers.\n";
array<int,12> arr4 = {1,3,5,2,2,4,6,8,10,11,9,7};
if (all_of(next(arr4.begin(), 3), prev(arr2.end(), 4), [](int i)->bool{return !(i%2);}))
cout << "All elements in diapason 3...8 are even numbers.\n";
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ g++ nechet.cc -o nechet
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./nechet
All the elements are odd numbers.
The elements begin from 4 are even numbers.
The elements begin from 4 are even numbers.
All elements in range 3...8 are even numbers.
- Вложения
-
- nechet.cc
- (1.18 КБ) 65 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Хронометраж высокой точности (он мне скоро сильно понадобится для сравнения производительности).
Можно, конечно, использовать API классического C, с использованием аппаратных штучек-дрючек (типа команды RDTSC) - хронологическое время с точностью до наносекунд
Но с C++ за годы наработано много собственной специфики...
Используем std::chrono::high_resolution_clock:
Можно, конечно, использовать API классического C, с использованием аппаратных штучек-дрючек (типа команды RDTSC) - хронологическое время с точностью до наносекунд
Но с C++ за годы наработано много собственной специфики...
Используем std::chrono::high_resolution_clock:
Код: Выделить всё
// high_resolution_clock example
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
int main ()
{
using namespace std::chrono;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
std::cout << "printing out 1000 stars...\n";
for (int i=0; i<1000; ++i) std::cout << "*";
std::cout << std::endl;
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds.";
std::cout << std::endl;
return 0;
}
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
Как и говорил ...
Смотрю что там на счёт move семантики в C++11 ...
Углубляемся в C++: move семантика и rvalue
Урок №192. Функция std::move()
Меня интересует скоростные разницы при передаче и возврате строк (std::string) в/из функции.
Пока так:
Код: Выделить всё
#include <iostream> // std::cout
#include <chrono> // high_resolution_clock example
using namespace std;
using namespace std::chrono;
string fun1(string s)
{
// do something with s ....
return s;
}
string fun2(string& s)
{
// do something with s ....
return s;
}
string fun3(string&& s)
{
// do something with s ....
return move( s );
}
string fun4(string& s)
{
// do something with s ....
return move( s );
}
int main( int argc, char *argv[] ) {
int len = 100000; // длина строки
if( argc > 1 && atoi( argv[ 1 ] ) != 0 )
len = atoi( argv[ 1 ] );
int rep = 100000; // число повторений
if( argc > 2 && atoi( argv[ 2 ] ) != 0 )
rep = atoi( argv[ 2 ] );
string etalon = string( len, 'm' ), dublic;
high_resolution_clock::time_point t1, t2;
duration<double> time_span;
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
dublic = fun1(etalon);
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время 1 = " << time_span.count() << " секунд "
<< ( dublic == string( len, 'm' ) ? "+" : "-" ) << endl;
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
dublic = fun2(etalon);
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время 2 = " << time_span.count() << " секунд "
<< ( dublic == string( len, 'm' ) ? "+" : "-" ) << endl;
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
etalon = fun3(move(etalon));
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время 3 = " << time_span.count() << " секунд "
<< ( etalon == string( len, 'm' ) ? "+" : "-" ) << endl;
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
etalon = fun4(etalon);
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время 4 = " << time_span.count() << " секунд "
<< ( etalon == string( len, 'm' ) ? "+" : "-" ) << endl;
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ g++ rvalue.cc -o rvalue
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue
время 1 = 0.571068 секунд +
время 2 = 0.569043 секунд +
время 3 = 0.00246565 секунд +
время 4 = 0.00223859 секунд +
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 1000000 50000
время 1 = 4.38805 секунд +
время 2 = 4.38243 секунд +
время 3 = 0.000819742 секунд +
время 4 = 0.000688928 секунд +
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 10000000 5000
время 1 = 11.2338 секунд +
время 2 = 11.5303 секунд +
время 3 = 8.4928e-05 секунд +
время 4 = 7.1658e-05 секунд +
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 100000000 100
время 1 = 7.75443 секунд +
время 2 = 7.76417 секунд +
время 3 = 4.26e-06 секунд +
время 4 = 3.562e-06 секунд +
И чем длиннее строка - тем разительнее разница (хотя в принципе это объяснимо) ... или я что-то неправильно понимаю в интерпретации результатов?
- Вложения
-
- rvalue.cc
- (2.14 КБ) 58 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
А что там происходит на коротких строках, с нормальной длиной, соизмеримой тому что мы имеем в реальной жизни?
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 50 40000000
время 1 = 1.88756 секунд +
время 2 = 1.7025 секунд +
время 3 = 0.668713 секунд +
время 4 = 0.557555 секунд +
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
В таких экспериментах нужно обязательно контроль того, что получается в итоге, особенно в итоге 1000000 копирований, когда промежуточный результат может исчезнуть в результате move-семантики...
Поэтому для достоверности переделаю вот так:
Код: Выделить всё
#include <iostream> // std::cout
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
string fun1(string s)
{
// do something with s ....
return s;
}
string fun2(string& s)
{
// do something with s ....
return s;
}
string fun3(string&& s)
{
// do something with s ....
return move( s );
}
string fun4(string& s)
{
// do something with s ....
return move( s );
}
int main( int argc, char *argv[] ) {
int len = 100000; // длина строки, argv[1]
if( argc > 1 && atoi( argv[ 1 ] ) != 0 )
len = atoi( argv[ 1 ] );
int rep = 100000; // число повторений, argv[2]
if( argc > 2 && atoi( argv[ 2 ] ) != 0 )
rep = atoi( argv[ 2 ] );
high_resolution_clock::time_point t1, t2;
duration<double> time_span;
const string inp = string( len, 'm' );
string etallon[] = { inp, inp, inp, inp };
for (int k = 0; k < sizeof( etallon ) / sizeof( etallon[0] ); k++ ) {
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
switch( k ) {
case 0:
etallon[k] = fun1( etallon[k] );
break;
case 1:
etallon[k] = fun2( etallon[k] );
break;
case 2:
etallon[k] = fun3( move( etallon[k] ) );
break;
case 3:
etallon[k] = fun4( etallon[k] );
break;
default:
break;
}
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время " << k << " = " << time_span.count() << " секунд "
<< "\t" << ( etallon[k] == inp ? "+" : "-" );
if( inp.length() <= 120 )
cout << " : (" << etallon[k].length() << ") " << etallon[k];
cout << endl;
}
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 60 50000000
время 0 = 2.44577 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 1 = 2.25954 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 2 = 0.929781 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 3 = 0.749893 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 10000000 1000
время 0 = 2.27179 секунд +
время 1 = 2.42483 секунд +
время 2 = 2.0953e-05 секунд +
время 3 = 1.7181e-05 секунд +
- Вложения
-
- rvalue.cc
- (1.75 КБ) 60 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: С++ в относительно новых стандартах
А ещё лучше (нагляднее) это можно сделать так:
Код: Выделить всё
#include <iostream> // std::cout
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
int main( int argc, char *argv[] ) {
int len = 100000; // длина строки, argv[1]
if( argc > 1 && atoi( argv[ 1 ] ) != 0 )
len = atoi( argv[ 1 ] );
int rep = 100000; // число повторений, argv[2]
if( argc > 2 && atoi( argv[ 2 ] ) != 0 )
rep = atoi( argv[ 2 ] );
high_resolution_clock::time_point t1, t2;
duration<double> time_span;
const string inp = string( len, 'm' );
string etallon[] = { inp, inp, inp, inp };
for (int k = 0; k < sizeof( etallon ) / sizeof( etallon[0] ); k++ ) {
t1 = high_resolution_clock::now();
for (int i = 0; i < rep; i++)
switch( k ) {
case 0:
etallon[k] = [](string s)->string{ return s; } ( etallon[k] );
break;
case 1:
etallon[k] = [](string &s)->string{ return s; } ( etallon[k] );
break;
case 2:
etallon[k] = [](string &&s)->string{ return s; } ( move( etallon[k] ) );
break;
case 3:
etallon[k] = [](string &s)->string{ return move( s ); } ( etallon[k] );
break;
default:
break;
}
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
cout << "время " << k << " = " << time_span.count() << " секунд "
<< "\t" << ( etallon[k] == inp ? "+" : "-" );
if( inp.length() <= 120 )
cout << " : (" << etallon[k].length() << ") " << etallon[k];
cout << endl;
}
}
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ g++ rvalue2.cc -o rvalue2
Код: Выделить всё
olej@nvidia:~/2020_WORK/Zodiac_Systems/OWN-DRAFT-TESTs$ ./rvalue 60 10000000
время 0 = 0.536146 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 1 = 0.482363 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 2 = 0.195454 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
время 3 = 0.155921 секунд + : (60) mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
- Вложения
-
- rvalue2.cc
- (1.58 КБ) 59 скачиваний
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 9 гостей