Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
프로그래밍 대회: C++11 이야기 (DRAFT)
약간의 코딩 스타일 얘기도 덤으로
Jongwook Choi
(@wookayin)
2015년 1월 24일
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Introduction
// elcome to C++11
using matrix = vector<vector<long>>;
auto fn = [=](const int x, const int y) { return x > y };
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
C++11
C++ 프로그래밍 언어의 최신 표준 스펙 (C++14는 아직..)
그동안 써왔던 예전 버전 : C++98, C++03
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 에 추가해야 함
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 기능들은
현재 사용가능한 (혹은 디폴트) 컴파일러 버전에서 대부분 지원함.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
다룰 내용들
C++11 의 신기능은 매우(..) 많지만, 어렵고 복잡한 거 다 빼고
프로그래밍 대회와 관련있는 실용적인(?) 것만 간단하게 훑어봅시다.
auto
range-based for
initializer lists
std::tuple
STL 컨테이너 개선
lambda function
move, r-value reference
기타 잡다한 내용
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
auto
map<pair<string, string>, vector<int> > M;
for(map<pair<string, string>, vector<int> >::iterator it = M.begin();
it != M.end(); ++ it)
{
// TF...
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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];
// ...
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Range-based for
C++11의 새로운 방식:
set<string> names;
for(const string &s : names) {
// ...
}
vector<vector<int> > G;
for(int v : G[u]) {
// ...
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Range-based for
std::map 은 pair 로 받아옵니다.
map<string, int> M;
for(auto &it : M) {
const string &key = it.first; // const !
int value = it.second;
// ...
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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) { ... }
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Range-based for : 주의 (2)
// iterate 4 times (includes null character!!)
for(char c : ”RGB”) { ... }
// iterate 3 times
for(char c : string(”RGB”)) { ... }
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Range-based for : FAQ
왜 이런걸 써야 하나?
편하다!
vector를 순회할 때, 값/레퍼런스 말고 index도 필요하면?
딱히 방법이 없다.
이럴 땐 옛날 방식을 사용하자
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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};
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Initializer lists
아마 이런 것이 유용할 것으로 생각됩니다 (..)
pair<int, string> getName() {
if(...) {
return make_pair(0, ”ACM-ICPC”);
}
else {
return {1, ”C++”}; // easy, huh?
}
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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} );
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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});
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Initializer lists : 응용 (2)
for문으로 돌리기도 뭐하고, copy&paste 신공으로 여러줄 쓰기도
뭐한데 특정 부분 또는 argument만 달라지는 경우에, range-based for
문과 함께 유용함.
for(const auto x : {2, 3, 5, 7}) {
foo(x);
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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에서는 안됨
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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; };
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
*/
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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를 쓰면 일어나지
않는다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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의
생성자에 그대로 전달된다고 생각하면 쉽다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
새로운 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;
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Hash set/map : 성능
대회에서 사용되는 수준의 data 크기로는, ordered set/map에 비해
약간의 성능 향상은 있다 (그러나 significant 하지는 않음)
32bit 정수형 타입, n = 1, 000, 000 : 2x ~ 3x faster
덩치큰 구조체 등 : hash 계산에 따라 비슷하거나 더 느릴수도 있다.
인터페이스 차이가 별로 없으므로, ordering이 중요하지 않다면 hash를
써도 손해볼 것은 없다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
사용자 정의 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;
}
};
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Lambda Function
Lambda : 익명 함수
// [ captures ]( parameters ){ body }
auto func = [](){};
func(); // call just like a classical function!
(익명) 함수를 값이나 객체처럼 취급이 가능하다 (e.g. 다른 함수의
argument로 넘길 수 있다!).
언어 차원에서 Closure 를 지원하고 있다. 그게뭐죠 먹는건가요
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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);
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 를 사용할 수 있다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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]);
}
/* ... */
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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);
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
} );
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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);
};
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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; }
*/
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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);
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Move Semantics
값 복사가 일어나지는 않나? Matrix면 100 × 100의 메모리 복사가
일어나서 느리지는 않는가?
옛날 C++에서는, 값 복사가 일어날 수도 있다.
RVO (Return Value Optimization) 최적화가 지원되는
컴파일러에서는 복사가 일어나지 않을 수도 있다.
C++11 에서는 move semantics 에 의해 (항상) 값 복사가 일어나지
않는다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 (!!!)
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
약간 오버해보자
std::move
Perfect Forwarding
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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’;
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
결론: R-Value, Move Semantics
그냥 C++11 컴파일 옵션을 넣기만 해도, (코드는 바뀐거 없어도)
vector, string 등의 연산자들이 (약간) 빨라진다.
string h = ”hello”, a = ”world”;
h = h + ” ” + a + ” ? ” + h + ” ICPC” + a;
사용자 정의 타입에 move semantics 를 지원하면 값 복사를 피할 수
있어 빨라질 수 있다. 근데 짜기가 어렵지
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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)
대회에서는 사용성이 별로 없다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 구린건 마찬가지)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Regex
정규식 기능이 C++11 부터 추가되었다. (주의) G++는 4.9.0
이상부터만 동작한다.
if( regex_match(”ABCD”, regex(”(A|B)C(.*)D”)) ) {
// ...
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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;
마라톤 매치 같은거 할 거 아니면 쓸모 없다
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Thread
멀티쓰레딩을 쉽게 할 수 있다. ICPC에서는 안되지만, GCJ나 HKcup
에서는 쓰면 유용할거에요
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
그 외 사소한 개선
연속된 > 사이에 공백이 없어도 됨
vector<vector<int> > a; // C++03...
vector<vector<int>> a; // C++03 : Error, C++11 : O
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
그 외 사소한 개선
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
nullptr
예전의 NULL은 (void*)0 이고, null pointer 는 nullptr 를 사용하면
됩니다.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
128-bit integer
C++11 표준은 아니지만 GCC에는 __int128_t (또는 __int128),
__uint128_t (또는 __uint128) 타입이 생겼다.
일부 환경에서만 됨 (e.g. 64-bit Linux on Intel)
10진수로 출력하는 내장 함수가 없다 (…)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Further References
cppreference.com : http://en.cppreference.com/w/
C++11 FAQ : http://www.stroustrup.com/C++11FAQ.html

More Related Content

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