Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

프로그래밍 대회: C++11 이야기

44.506 visualizaciones

Publicado el

ACM-ICPC, Topcoder 등 프로그래밍 대회를 위한 간단한 C++11 소개

Publicado en: Tecnología
  • Sé el primero en comentar

프로그래밍 대회: C++11 이야기

  1. 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 프로그래밍 대회: C++11 이야기 (DRAFT) 약간의 코딩 스타일 얘기도 덤으로 Jongwook Choi (@wookayin) 2015년 1월 24일
  2. 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction // elcome to C++11 using matrix = vector<vector<long>>; auto fn = [=](const int x, const int y) { return x > y };
  3. 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++11 C++ 프로그래밍 언어의 최신 표준 스펙 (C++14는 아직..) 그동안 써왔던 예전 버전 : C++98, C++03
  4. 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++11 : Current Status 2011년 8월, C++11 언어 스펙 확정 컴파일러 현황 GNU C++ : Complete (G++ 4.8, 4.9 for regex) Clang C++ : Complete (Clang 3.3) MSVC++ : Almost Complete (VS 2012), and much more (VS 2013) C++11 를 활성화하려면, --std=c++11 (or --std=c++0x) 옵션을 command line 에 추가해야 함
  5. 5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C++11 : Current Status Compatibility Chart g++ : http://gcc.gnu.org/projects/cxx0x.html MSVC : http://msdn.microsoft.com/en-us/library/hh567368.aspx PS에서 사용되는 코드 수준에서 필요한 대부분의 C++11 기능들은 현재 사용가능한 (혹은 디폴트) 컴파일러 버전에서 대부분 지원함.
  6. 6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 다룰 내용들 C++11 의 신기능은 매우(..) 많지만, 어렵고 복잡한 거 다 빼고 프로그래밍 대회와 관련있는 실용적인(?) 것만 간단하게 훑어봅시다. auto range-based for initializer lists std::tuple STL 컨테이너 개선 lambda function move, r-value reference 기타 잡다한 내용
  7. 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auto map<pair<string, string>, vector<int> > M; for(map<pair<string, string>, vector<int> >::iterator it = M.begin(); it != M.end(); ++ it) { // TF... }
  8. 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auto auto : 컴파일 타임에 변수의 type을 자동으로 추론하여 선언하기 map<pair<string, string>, vector<int> > M; for(auto it = M.begin(); it != M.end(); ++ it) { // Olleh! } // map<pair<string, string>, vector<int>>::iterator it;
  9. 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for (STL 컨테이너 순회를 위한) 옛날 방식: set<string> names; for(set<string>::iterator it = names.begin(); it != names.end(); ++ it) const string &s = *it; } vector<vector<int> > G; for(unsigned i = 0; i < G[u].size(); ++i) { int v = G[u][i]; // ... }
  10. 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for C++11의 새로운 방식: set<string> names; for(const string &s : names) { // ... } vector<vector<int> > G; for(int v : G[u]) { // ... }
  11. 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for std::map 은 pair 로 받아옵니다. map<string, int> M; for(auto &it : M) { const string &key = it.first; // const ! int value = it.second; // ... }
  12. 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for : 주의 (1) range-based for문에서 선언하는 변수가 레퍼런스(reference) 타입이 아니면, 값 복사가 발생하므로 주의합니다. auto 도 마찬가지입니다. vector<LargeStruct> data; // rong! (copy by value) for(LargeStruct a : data) { ... } for(auto a : data) { ... } // Preferred way (avoid copying) for(auto& a : data) { ... } for(const auto& a : data) { ... }
  13. 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for : 주의 (2) // iterate 4 times (includes null character!!) for(char c : ”RGB”) { ... } // iterate 3 times for(char c : string(”RGB”)) { ... }
  14. 14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Range-based for : FAQ 왜 이런걸 써야 하나? 편하다! vector를 순회할 때, 값/레퍼런스 말고 index도 필요하면? 딱히 방법이 없다. 이럴 땐 옛날 방식을 사용하자
  15. 15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializer lists STL 컨테이너를 더 간단하게 초기화할 수 있다. (기존에는 딱히 좋은 방법이 없었음) vector<int> a = {1, 2, 3, 4}; map<string, int> b = { {”a”, 1}, {”b”, 2} }; pair<int, long long> c = {3, 4LL}; pair<vector<int>, pair<char, char>> d = { {1, 2, 3}, {’A’, ’B’} } tuple<int, string, int> e = {2222, ”Yellow”, 22};
  16. 16. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializer lists 아마 이런 것이 유용할 것으로 생각됩니다 (..) pair<int, string> getName() { if(...) { return make_pair(0, ”ACM-ICPC”); } else { return {1, ”C++”}; // easy, huh? } }
  17. 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializer lists 사용자 정의 구조체/클래스도 됨! struct vector3 { int x, y, z; vector3(int x=0, int y=0, int z=0) : x(x), y(y), z(z) { } }; vector3 O = vector3(0, 0, 0); // 생성자 사용 vector3 V = {1, 2, 3}; // initializer list 사용 // 생성자 없이 explicit type을 주어 값 생성 vector3_add( vector3{0, 0, 0}, vector3{0, 0, 0} ); // 함수 파라메터에 따라 자동으로 type 추론이 가능 vector3_add( {0, 0, 0}, {0, 0, 0} );
  18. 18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializer lists : 응용 // the old-way int minValue = min(x, min(y, z)); // C++11 에서는, std::min, std::max 등의 함수가 // std::initializer_list<T> 타입을 받을 수 있도록 overload 되어 있음 int minValue = min({x, y, z}); int maxValue = max({x, y, z}); tie(minValue, maxValue) = minmax({p, q, r, s});
  19. 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializer lists : 응용 (2) for문으로 돌리기도 뭐하고, copy&paste 신공으로 여러줄 쓰기도 뭐한데 특정 부분 또는 argument만 달라지는 경우에, range-based for 문과 함께 유용함. for(const auto x : {2, 3, 5, 7}) { foo(x); }
  20. 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . In-class member initializers struct 또는 class의 field를 초기화할 수 있다. (생성자에 귀찮게 매번 안 써도 됨) class AwesomeLibrary { int sum = 0; // C++03 : Error, C++11 : O int n; }; G++ 에서는 4.7 이상부터 지원, MSVC 2012에서는 안됨
  21. 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tuple 기존에는 두개짜리 std::pair<T1, T2> 만 있었다. 값 3개를 묶어서 들고 다니려면 어떻게 해야할까요? // 1. nested pair // a.first, a.second.first, a.second.second (orz) pair<int, pair<int, int> > a; // 2. 구조체 직접 작성 struct xyz { int x, y, z; };
  22. 22. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tuple // tuple<T1, T2, T3, T4, ...> tuple<int, string, int> t(1, ”hello”, -1); // make_pair 처럼 make_tuple 을 사용 t = make_tuple(1, ”hello”, -1); // std::get - tuple 에서 값 추출하기 int v1 = get<0>(t); // 1 string v2 = get<1>(t); // hello int z = get<2>(t); // -1
  23. 23. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tuple, tie std::tie를 쓰면 tuple 의 값을 여러 변수에 동시에 받아올 수 있어요. int a = 3, b = 4; tie(b, a) = make_tuple(a, b); // b=3, a=4 int x, y; tie(x, y, ignore) = make_tuple(3, 4, 5); // x=3, y=4
  24. 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tuple 예제: lexicographical comparison 쉽게 하기 sort(a.begin(), a.end(), [&](const Elem &x, const Elem &y) { return make_tuple(x.score, -x.age, x.submission) < make_tuple(y.score, -y.age, y.submission); }); /* x.score != y.score ? (x.score < y.score : (x.age != y.age ? x.age > y.a if(x.score != y.score) return x.score < y.score; */
  25. 25. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tuple 예제: lexicographical comparison 쉽게 하기 Smaller number of vowels (aeiou) On tie, larger length On tie, lexicographically smallest string findBest(string a, string b, string c) { auto q = min({ make_tuple( vowels(a), -(int)a.size(), a ), make_tuple( vowels(b), -(int)b.size(), b ), make_tuple( vowels(c), -(int)c.size(), c ) }); return get<2>(q); } (참고) make_tuple을 쓰면 copy가 일어나고, std::tie를 쓰면 일어나지 않는다.
  26. 26. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . STL 컨테이너 vector, list, queue, deque 등에 메소드 emplace(...) 혹은 emplace_back(...) 등이 추가되었다. vector< pair<int, int> > A; A.push_back( make_pair(3, 4) ); // {3, 4}를 추가 A.emplace_back( 3, 4 ); // 위와 같은 일을 함. queue< tuple<int, int, int> > Q; // Q.push( {1, 2, 3 }); Q.emplace( 1, 2, 3 ); 대강 말하면, 모든 argument가 컨테이너 내 element의 type의 생성자에 그대로 전달된다고 생각하면 쉽다.
  27. 27. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 새로운 STL 컨테이너 : unordered_set, unordered_map std::set, std::map : ‘sorted-key’ set/dictionary 내부 구현은 R/B Tree 를 사용함 – O(log n) std::unordered_set, std::unordered_map : hash 를 이용한 구현 (이론적으로) O(1) 시간복잡도 std::set, std::map 와 (거의) 같은 인터페이스 자매품으로 std::unordered_multiset, std::unordered_multimap 도 있다. unordered_map<long long, int> pows; for(int i=0; i<63; ++i) pows[1LL<<i] = i;
  28. 28. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hash set/map : 성능 대회에서 사용되는 수준의 data 크기로는, ordered set/map에 비해 약간의 성능 향상은 있다 (그러나 significant 하지는 않음) 32bit 정수형 타입, n = 1, 000, 000 : 2x ~ 3x faster 덩치큰 구조체 등 : hash 계산에 따라 비슷하거나 더 느릴수도 있다. 인터페이스 차이가 별로 없으므로, ordering이 중요하지 않다면 hash를 써도 손해볼 것은 없다.
  29. 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 사용자 정의 struct에 hash를 추가하는 법 struct MyType { string name; int age; // implement operator == }; /* std::hash<T> 에 operator() 를 구현합니다. */ namespace std { template <> struct hash<MyType> { size_t operator (const MyType &o) const { size_t h; h = (hash<string>())(name); h ^= (hash<int>())(age) >> 1; return h; } }; }
  30. 30. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Function Lambda : 익명 함수 // [ captures ]( parameters ){ body } auto func = [](){}; func(); // call just like a classical function! (익명) 함수를 값이나 객체처럼 취급이 가능하다 (e.g. 다른 함수의 argument로 넘길 수 있다!). 언어 차원에서 Closure 를 지원하고 있다. 그게뭐죠 먹는건가요
  31. 31. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : STL (거의) 모든 STL 알고리즘은 lambda 함수를 지원합니다. vector<int> v = ...; for_each(v.begin(), v.end(), [](int x) { cout << x << ’ ’; }); // 특히 정렬에서 lambda 함수가 가장 유용하다. // comparator를 번거롭게 만들거나, 먼 곳에 두지 않아도 됨! sort(a.begin(), a.end(), [&](int x, int y) { return priority[x] > priority[y]; }); auto by_abs = [](int x, int y) { return abs(x) < abs(y); }); sort(a.begin(), a.end(), by_abs);
  32. 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : Local functions C++03 에서는, local type 선언은 가능하지만 template argument 로 사용이 불가능하다. 따라서 sort의 comparator 로 사용할 수 없어 함수 바깥으로 빼야하는 불편함이 있었다. void localFunction( vector<int> &data ) { struct AbsComparator { bool operator() (const int a, const int b) { return abs(a) < abs(b); }; }; sort(data.begin(), data.end(), AbsComparator()); // ERROR in C++03, O in C++11 }
  33. 33. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : Local functions 마찬가지로 lambda를 사용하면, 해당 함수가 사용되는 곳에서 코드를 작성할 수 있으므로 전역 변수의 사용을 피하고 code의 locality를 키울 수 있으므로 좋다. // Using Lambda : ind of local functions (even can capture local variables) void localFunction( const vector<point> &P ) { const point O = P[0]; // reference 사용하지 않도록 주의 (why?) auto by_distance = [&](const point &A, const point &B) { double OA = (A - base).norm(); double OB = (B - base).norm(); return OA < OB; }; sort(P.begin(), P.end(), by_distance); // O } Closure 덕택에 contextual variable 를 사용할 수 있다.
  34. 34. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : 예제 (1) int solve(vector<int> &a, vector<int> &b) { int n = (int) a.size(); int S = 0, T = V - 1; int V = 2 * n + 2; auto L = [&](int x) { return x + 1; }; auto R = [&](int x) { return x + 1 + n; }; NetworkFlow f(V); for(int i=0; i<n; ++i) { f.addEdge(S, L(i), a[i]); f.addEdge(L(i), R(i), a[i]); f.addEdge(R(i), T, b[i]); } /* ... */ }
  35. 35. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : 예제 (2) double ternary(function<double (double)> f, double l, double r) { for(int iter = 0; iter < 100; ++ iter) { double p = (l * 2 + q) / 3, q = (l + 2 * q) / 3; if (f(p) > f(q)) r = q; else l = p; } return (l + r) / 2.0; } double solve() { auto f = [&](double x) -> double { return x * x; }; double x0 = ternary(f, 0.0, 1.0); return f(x0); }
  36. 36. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda Goodnesses : 예제 (3) /* akarta 2013 */ RangeTree t0([](long long x) -> long long { return x; } ); RangeTree t1([](long long x) -> long long { return (x * (x + 1) / 2) % MOD; } ); RangeTree t2([](long long x) -> long long { return (x * (x + 1) * (2 * x + 1) / 6 ) % MOD; } ); RangeTree t3([](long long x) -> long long { return (((x * (x + 1) / 2) % MOD) * ((x * (x + 1) / 2) % MOD)) % MOD; } );
  37. 37. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda : Recursive Recursive 익명함수도 가능하다. 다만, C++14 전까지는 형태가 약간 이상함(..) std::function<int(int)> f; // include <functional> f = [&f](int x) -> int { if(x <= 1) return x; return f(x - 1) + f(x - 2); };
  38. 38. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda : Recursive (예제) 어떤 함수 안에서만 필요한 DFS 짜야하는데.. 전역변수로 빼긴 좀 싫고.. bool isGraphConnected(vector<vector<int>> &G) { vector<bool> visited(G.size(), false); std::function<void (int)> dfs = [&](int u) { if (visited[u]) return; for (int v : G[u]) dfs(v); }; dfs(0); for(size_t i = 0; i < G.size(); ++ i) if (!visited[i]) return false; return true; }
  39. 39. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lambda + STL Algorithms vector<int> primes = { 2, 3, 5, 7, 11 }; auto is_even = [](int n) { return (n & 1) == 0; } bool allEven = all_of(primes.begin(), primes.end(), is_even); /* allEven = false; for(int x : primes) if(! is_even(x)) { allEven = false; break; } */
  40. 40. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Move Semantics Matrix 곱셈 함수를 만든다고 가정해봅시다. typedef vector<vector<int>> Matrix; // output 대상을 argument로 넣는 것은 // 일반적으로 좋은 코딩 습관이 아닙니다. void multiply(const Matrix &A, const Matrix &B, Matrix &C); // C를 바깥에서 생성해야 하므로 사용하기도 난감합니다. Matrix C; multiply(A, B, C); print(C);
  41. 41. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Move Semantics C++ 스타일로 하면: // 값(Matrix)으로 리턴합니다. Matrix operator * (const Matrix &A, const Matrix &B) { size_t n = A.size(); Matrix C(n, n); REP(i, n) REP(j, n) REP(k, n) C[i][j] += A[i][k] * B[k][j]; return C; // return by value } // syntax도 깔끔하고, 직관적인 operator 스타일로 쓸 수도 있음.. Matrix E = (D * D) + I; E = E * E;
  42. 42. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Move Semantics 값 복사가 일어나지는 않나? Matrix면 100 × 100의 메모리 복사가 일어나서 느리지는 않는가? 옛날 C++에서는, 값 복사가 일어날 수도 있다. RVO (Return Value Optimization) 최적화가 지원되는 컴파일러에서는 복사가 일어나지 않을 수도 있다. C++11 에서는 move semantics 에 의해 (항상) 값 복사가 일어나지 않는다.
  43. 43. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R-Value Reference L-Value, R-Value 에 대해 자세히 설명하려면 어려우니까 (컴파일러 들으세요..), 간단히 말해서 L-Value는 주소값이 있는 변수, R-Value는 주소값이 없는 ‘임시 객체’ 라고 생각하면 됩니다. vector<int> concat(const vector<int> &a, const vector<int> &b); vector<int> range(int n); vector<int>& foo(int); vector<int> x; // L-value cout << range(10) // --------- : R-value cout << foo(0); // ------ : L-value
  44. 44. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example 아래와 같은 경우가 종종 있다(?) 어떻게 고쳐야 할까? vector<int> concat (vector<int> &a, vector<int> &b) { // (!) // ... } vector<int> range (int n) { /* ... */ } int main() { vector<int> c; c = concat ( vector<int> { -1 }, range(5) ); // (?) for(int x : c) cout << x << ’ ’; cout << endl; return 0; }
  45. 45. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example 해결책 1: Reference가 아닌 값으로 함수를 선언한다. (문제점) 값 복사가 일어난다. vector<int> concat (vector<int> a, vector<int> b) { // (!!!!!!!!) // ... } vector<int> range (int n) { /* ... */ } int main() { vector<int> c; c = concat ( vector<int> { -1 }, range(5) ); // (?) for(int x : c) cout << x << ’ ’; cout << endl; return 0; }
  46. 46. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example 해결책 2: Reference를 유지하고, 불편하게 사용한다. (문제점) 코드의 가독성이 떨어지고 불필요한 변수 선언을 해야 한다. vector<int> concat (vector<int> &a, vector<int> &b) { // (!) // ... } vector<int> range (int n) { /* ... */ } int main() { vector<int> a = vector<int> { -1 }, b = range(5); vector<int> c = concat( a, b ); // (!!!!!!!!) for(int x : c) cout << x << ’ ’; cout << endl; return 0; }
  47. 47. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example 해결책 3: R-Value Reference를 사용한다. (문제점) L-Value 인자는 R-Value로 implicit 변환이 안된다. vector<int> concat (vector<int> &&a, vector<int> &&b) { // (!!!!!!!!) // ... } vector<int> range (int n) { /* ... */ } int main() { vector<int> c; c = concat ( vector<int> { -1 }, range(5) ); // (?) for(int x : c) cout << x << ’ ’; cout << endl; return 0; }
  48. 48. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Move Constructor Move Constructor 가 있는 클래스(STL 컨테이너)에 대해서는, 임시 객체(R-value)를 받아 객체를 생성할 수 있다. 이 때, 값 복사 없이 메모리 이동하는 꼴이 되는데, 이것을 move semantic 이라 한다. template<typename T> struct vector { vector(); vector(size_t size); // ... constructors vector(vector<T> &a); // copy constructor (복사) vector(vector<T> &&a); // move constructor (!!!) }
  49. 49. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example 완벽한 해법은 아니지만 일단 아래와 같이 하면 […] vector<int> concat (vector<int> &&a, vector<int> &&b) { // ... } vector<int> concat (const vector<int> &a, const vector<int> &b) { // ... } vector<int> range (int n) { /* ... */ } { // ... c = concat ( vector<int> { -1 }, range(5) ); // L-Value c = concat ( c, c ); // R-Value }
  50. 50. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 약간 오버해보자 std::move Perfect Forwarding
  51. 51. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Another Example 이런 코드를, 성능 걱정 없이 그냥 만들어 쓰면 됩니다. vector<int> generate_array(int n) { vector<int> a; a.push_back(A); for(int i=1; i<n; ++i) a.push_back((a.back() * B + C) % D); return a; } for (auto x : generate_array(1000000)) // no copy !!! cout << x << ’n’;
  52. 52. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 결론: R-Value, Move Semantics 그냥 C++11 컴파일 옵션을 넣기만 해도, (코드는 바뀐거 없어도) vector, string 등의 연산자들이 (약간) 빨라진다. string h = ”hello”, a = ”world”; h = h + ” ” + a + ” ? ” + h + ” ICPC” + a; 사용자 정의 타입에 move semantics 를 지원하면 값 복사를 피할 수 있어 빨라질 수 있다. 근데 짜기가 어렵지
  53. 53. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . std::array array<int, 6> a = { 1, 2, 3 }; // int a[6]; vector 와 달리, 크기가 고정된 정적(static) 배열이다. int[] 와의 차이점은? STL algorithm 함수들에 적용이 가능함 (e.g. begin, end) 값 복사, 사전순 비교 등이 쉽게 가능 (as operator, no memcpy!) assertive 하게 동작 (out-of-index 일 때 바로 throw) 대회에서는 사용성이 별로 없다.
  54. 54. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standardized Timer Library See std::chrono. 윈도우/리눅스 등 여러 플랫폼에서 공통으로 사용가능하다. using namespace std::chrono; // include <chrono> auto _start = system_clock::now(); // or high_resolution_clock::now() /* SOME EAVY OBS here */ auto _end = system_clock::now(); // or high_resolution_clock::now() long millisecs = duration_cast<milliseconds>(_end - _start).count(); Linux only 라면.. gettimeofday() 써도 된다 (API 구린건 마찬가지)
  55. 55. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Regex 정규식 기능이 C++11 부터 추가되었다. (주의) G++는 4.9.0 이상부터만 동작한다. if( regex_match(”ABCD”, regex(”(A|B)C(.*)D”)) ) { // ... }
  56. 56. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Random Library 더 좋은 랜덤 성능! (rand() 는 uniformity가 떨어지고, RAND_MAX가 32767인 머신도 있다) std::mt19937 eng; // Mersenne Twister std:::uniform_int_distribution<int> U(-100, 100); for (int i = 0; i < n; ++i) cout << U(eng) << std; 마라톤 매치 같은거 할 거 아니면 쓸모 없다
  57. 57. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Thread 멀티쓰레딩을 쉽게 할 수 있다. ICPC에서는 안되지만, GCJ나 HKcup 에서는 쓰면 유용할거에요
  58. 58. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 그 외 사소한 개선 연속된 > 사이에 공백이 없어도 됨 vector<vector<int> > a; // C++03... vector<vector<int>> a; // C++03 : Error, C++11 : O
  59. 59. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 그 외 사소한 개선 std::to_string string s = std::to_string(10); string s = std::to_string(3.1415926535); std::stoi, std::stol, std::stoll int x = stoi(”-1”); long long y = stoll(”2147483648”); long long z = stoll(”1000...0000”, 0, 2); // 4294967296
  60. 60. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . nullptr 예전의 NULL은 (void*)0 이고, null pointer 는 nullptr 를 사용하면 됩니다.
  61. 61. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128-bit integer C++11 표준은 아니지만 GCC에는 __int128_t (또는 __int128), __uint128_t (또는 __uint128) 타입이 생겼다. 일부 환경에서만 됨 (e.g. 64-bit Linux on Intel) 10진수로 출력하는 내장 함수가 없다 (…)
  62. 62. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Further References cppreference.com : http://en.cppreference.com/w/ C++11 FAQ : http://www.stroustrup.com/C++11FAQ.html

×