SlideShare a Scribd company logo
1 of 53
포트폴리오에서 사용한
Modern C++
데브루키 쿵쾅(김광일)
STL(Standard Template Library)
C++에서 제공하는 자료구조, 알고리즘, 등을 사용하기 편하게 만든 표준 템플릿 라이브러리
std::vector, std::list, std::map, std::sort, std::for_each 등이 있다.
반복자(iterator)
STL 컨테이너의 내부 요소를 순회하는 객체로 포인터와 유사하나 포인터와는 다르다.
1 2 3 4 5std::vector<int> vec
std::vector<int>::iterator iter
vec.begin() vec.end()
auto 키워드
c++11
변수를 초기화하는 동시에 자료형을 추론해주는 키워드. 초기화를 하지 않을 경우 사용할 수 없다.
auto num; // error
auto num = 1; // int
auto num = 1.f // float
auto num = 1.0 // double
auto 키워드
c++11
vector<int> vec;
auto iter = vec.begin(); // vector<int>::iterator
위와 같이 긴 반복자 변수를 auto 키워드로 줄일 수 있다.
auto func = []() { std::cout << “Func” }; // 함수 포인터 타입
범위 기반 for문
c++11
배열 또는 컨테이너에 접근하여 모든 원소를 순회하는 for문
일반 배열에서는 범위기반이 동작하지만 동적 배열에는 동작하지 않는다.
int arr[10] = {}
for(int i = 0; i < 10; ++i)
std::cin >> arr[i];
int arr[10] = {}
for(int num : arr)
std::cin >> num;
범위 기반 for문
c++11
위와 같이 STL 컨테이너 순회에 응용할 수 있다.
std::vector<int> vec(10, 0);
auto iter = vec.begin();
auto iter_end = vec.end();
for( ; iter != iter_end; ++iter)
std::cin >> *iter;
std::vector<int> vec(10, 0);
for(auto& num : vec)
std::cin >> num;
std::vector<int> vec(10, 0);
for(size_t i = 0; i < vec.size(); ++i)
std::cin >> vec[i];
범위 기반 for문
c++11
override 키워드
c++11
class Parent
{
virtual void Out() { std::cout << “Parent”
<< std::endl;
}class Derived : public Parent
{
virtual void Out() override { std::cout << “Derived ”
<< std::endl;
void MyOut() override; // error
}
가상 함수를 자식 클래스에서 오버 라이딩 할 때
명시적으로 선언할 수 있다.
부모 클래스에서 선언되지 않은 함수를 명시적
으로 표기할 때 에러를 발생한다.
override 키워드
c++11
GameObject.h SpaceMarin.h
Uniform 초기화
c++11
모든 오브젝트 타입에 대해 동일한 방식으로 리스트형 초기화를 할 수 있는 기능.
int i = { 1 };
int arr[5] = { 1, 2, 3, 4, 5 };
std::vector<int> vec = { 1, 2, 3 };
struct Point
{
float a, float b;
}
Point pt = {};
Uniform 초기화
c++11
class Vector3
{
Vector3() {};
Vector3(float _x, float _y, float _z)
{ x = _x; y = _y; z = _z; }
float x, y, z;
}
Vector3 player_position = {};
Vector3 enemy_position = { 5.f, 0.f, 10.f };
다음과 같은 경우 player_position의 멤버 변수는 초기화 되
지 않음. 아무런 초기화도 하지 않는 생성자가 호출되었기
때문이다.
enemy_position의 경우 Vector3(float _x, float _y, float _z)
생성자를 호출하여 Uniform 초기화를 수행.
클래스의 생성 형식을 유지하고 싶다면 explicit 키워드를 사
용하자.
Uniform 초기화
c++11
명시적 기본 설정 및 삭제
c++11
Effective C++에서 복사가 일어나면 안되는 객체에 대하여 복사를 막는 방법으로 아래와 같이
복사생성자를 private로 하는 방법이 나와있다.
class Player
{
private:
Player(const Player& rhs);
};
명시적 기본 설정 및 삭제
c++11
C++11 부터는 클래스를 작성하면 기본적으로 만들어주는 생성자, 복사 생성자, 대입연산자를
명시적으로 선언하거나 삭제할 수 있다.
class Player
{
Player() = default;
Player(const Player& rhs) = delete;
};
명시적 기본 설정 및 삭제
c++11
enum vs enum class
c++11
enum ObjectTag { Player, Enemy, Environment, End };
enum ColliderTag { Enemy, Player, Environment, End };
std::list<CGameObject*> object_list_[End]; (o)
std::list<CGameObject*> object_list_[ObjectTag::End];
(o)
enum class ObjectTag { Player, Enemy, Environment, End };
enum class ColliderTag { Player, Enemy, Environment, End };
std::list<CGameObject*> object_list_[End]; (x)
std::list<CGameObject*> object_list_[ObjectTag::End]; (x)
C++에서는 enum의 값을 int 형태로 처리한다. 왼쪽과 같이 기존의 enum으로 선언할 경우 정적
배열의 enum 개수만큼 초기화 할 수 있다. 그리고 enum 타입을 생략하고 사용할 수 있다. 하지
만 ObjectTag 타입에 선언된 이름과 ColliderTag에 선언된 이름은 중복될 경우 타입을 명시적
으로 하지 않으면 ColliderTag의 값으로 인식한다.
enum vs enum class
c++11
enum ObjectTag { Player, Enemy, Environment, End };
enum ColliderTag { Enemy, Player, Environment, End };
std::list<CGameObject*> object_list_[End]; (o)
std::list<CGameObject*> object_list_[ObjectTag::End];
(o)
enum class ObjectTag { Player, Enemy, Environment, End };
enum class ColliderTag { Player, Enemy, Environment, End };
std::list<CGameObject*> object_list_[End]; (x)
std::list<CGameObject*> object_list_[ObjectTag::End]; (x)
오른쪽의 enum class의 경우 명시적으로 enum 타입을 사용해야 열거형 값을 사용할 수 있다.
단 unsigned int로 인식은 하지만 enum 타입때문에 정적 배열에 사용할 수 없다.
enum vs enum class
c++11
C++에서는 enum의 값을 int로 처리한다.
enum vs enum class
c++11
push_back vs emplace_back
c++11
push_back의 경우 기존의 STL 컨테이너에 원소를 넣을 때 사용하는 함수이다.
emplace_back는 C++11부터 추가된 STL 컨테이너에 원소를 넣을 때 사용하는 함수이다.
둘은 같은 역할을 한다. 하지만 차이점이 존재한다.
std::vector<Object*> vec_object; vec_object.push_back(new Object);
vec_object.emplace_back(new Object);
push_back vs emplace_back
c++11
int main()
{
std::vector<Object> vec;
vec.reserve(100);
std::cout << "push_back: "
<< std::endl;
vec.push_back(5);
std::cout << std::endl;
std::cout << "emplace_back: "
<< std::endl;
vec.emplace_back(5);
std::cout << std::endl;
return 0;
}
#include <iostream>
#include <vector>
class Object
{
public:
Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; }
Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자"
<< std::endl; }
~Object() { std::cout << "소멸자" << std::endl; }
private:
int hp = 0;
};
위 코드를 실행한다.
push_back vs emplace_back
c++11
int main()
{
std::vector<Object> vec;
vec.reserve(100);
std::cout << "push_back: "
<< std::endl;
vec.push_back(5);
std::cout << std::endl;
std::cout << "emplace_back: "
<< std::endl;
vec.emplace_back(5);
std::cout << std::endl;
return 0;
}
#include <iostream>
#include <vector>
class Object
{
public:
Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; }
Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자"
<< std::endl; }
~Object() { std::cout << "소멸자" << std::endl; }
private:
int hp = 0;
};
다음과 같은 결과를 나타낸다.
push_back vs emplace_back
c++11
int main()
{
std::vector<Object> vec;
vec.reserve(100);
std::cout << "push_back: "
<< std::endl;
vec.push_back(5);
std::cout << std::endl;
std::cout << "emplace_back: "
<< std::endl;
vec.emplace_back(5);
std::cout << std::endl;
return 0;
}
#include <iostream>
#include <vector>
class Object
{
public:
Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; }
Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자"
<< std::endl; }
~Object() { std::cout << "소멸자" << std::endl; }
private:
int hp = 0;
};
push_back과 emplace_back는 각각 &&(R-Value Reference)를 받는 함수로 오버로딩 되어있다.
이때 push_back의 경우 임시 객체를 생성하고 vector에 삽입 후 삭제까지한다. 반면
emplace_back의 경우 원소의 그 위치에 바로 생성하는 형태이다.
push_back vs emplace_back
c++11
중간에 원소를 삽입하는 Insert와 같은 역할을 하는 emplace 함수도 있다.
vector는 emplace_back, emplace
list는 emplace_front, emplace_back, emplace
map은 emplace 함수가 각각 구현되어있다.
R-Value Reference
c++11
int num = 1;
L-Value R-Value
먼저 L-Value와 R-Value를 알아본다.
위 변수와 같이 왼쪽에 있는 값이 L-Value, 오른쪽에 있는 값이 R-Value이다.
R-Value Reference
c++11
int num = 1;
L-Value R-Value
보통 왼쪽에는 변수를 선언할 것이고 오른쪽에는 다른 변수를 대입하거나 임의의 상수 또는 임시
객체 등을 사용할 것이다. 이때 임의의 상수 리터럴 변수와 임시 객체 등은 R-Value이다.
R-Value Reference
c++11
int num = 1;
int num2 = num;
위 상태의 경우 num은 오른쪽에 있지만 L-Value 이다.
R-Value Reference
c++11
int num = 5;
int 1 = num; (Error)
R-Value를 조금 더 쉽게 구분하자면 왼쪽에 올 수 없는 값(리터럴, 임시 객체 등은 왼쪽에 올 수 없
다)을 R-Value라고 생각하면 될 것이다.
class A {};
A a;
A() = a; (Error)
R-Value Reference
c++11
리터럴 상수 5를 num이라는 R-Value Reference에 초기화 하였다. 기존의 레퍼런스는 위와 같이
리터럴 상수 또는 임시 객체를 담을 수 없다.
int& r_num = 5; (Error)
int&& num = 5;
class A {};
A& a = A(); (Error)
A&& a = A();
Lambda
c++11
람다식은 무명 함수(이름 없는 함수)라고 부른다.
이름 그대로 함수의 이름이 존재하지 않는 함수이다.
[&](int a) -> int { return a; }
[ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
Lambda
c++11
람다식 구현부에서는 람다식 외부의 변수 또는 함수를 사용할 수 없다. 이때 캡처절을 이용하여
외부 지역의 변수 또는 클래스의 멤버 함수를 가져와서 사용할 수 있다.
[&](int a) -> int { return a; }
[ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
Lambda
c++11
[]: 공백일 때에는 아무 것도 캡처하지 않는 상태이다.
[=]: 외부 지역의 모든 변수와 클래스의 경우 멤버 함수 주소까지 값(Call by Value)으로 캡처한다.
[&]: 외부 지역의 모든 변수와 클래스의 경우 멤버 함수 주소까지 레퍼런스(Call by Reference)로 캡처한다.
[x]: 외부 지역의 변수 x를 값으로 캡처한다.
[&x]: 외부 지역의 변수 레퍼런스로 캡처한다.
[&](int a) -> int { return a; }
[ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
Lambda
c++11
[x, &]: x만 값으로 그 외에는 레퍼런스로 캡처한다.
[&x, =]: x만 레퍼런스로 그 외에는 값으로 캡처한다.
[x, &y]: x는 값으로, y는 레퍼런스로 캡처한다.
[&](int a) -> int { return a; }
[ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
Lambda
c++11
그 외에 매개변수절은 기존 함수와 동일하고 반환형의 경우 명시적으로 선언할 수 있고 따로 명
시하지 않아도 return 값에 따라 반환 타입을 결정해준다. 구현부에는 함수의 내용을 구현하면
된다.
[&](int a) -> int { return a; }
[ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
Lambda
c++11
다음과 같이 STL 알고리즘 함수에 임의의 조건자를 넣을 때 람다식으로 만들어서 넣을 수 있다.
함수자 또는 함수객체를 대체할 수 있으며 함수 객체의 장점인 멤버 변수를 가질 수 있는 부분
을 캡처절을 활용하여 대체할 수 있다.
std::function
<functional>
c++11
함수 포인터를 유연하게 사용하기 위한 변수. 함수 포인터의 경우 람다, 함수 객체를 담을 수 없
다.
C++11 부터는 유연성이 강한 함수를 담을 수 있는 변수를 제공한다.
std::function<void()> func = []()->void { std::cout << “Hello World” << std::endl; };
std::function<int(int)> func = [](int a)->int { return a; };
std::function
<functional>
c++11
람다식 + std::function을 이용한 AI
random
<random>
c++11
seed값을 통하여 난수를 반환하는 rand 함수는 매우 한계가 크다.
C++11부터는 random 클래스를 제공하여 좀 더 확실한 난수를 얻을 수 있다.
random_device를 이용하면 하드웨어의 리소스를 사용하여 시드를 설정하여 랜덤값을 가져온
다.
std::random_device _random_device;
std::mt19937 _mt(_random_device());
std::uniform_int_distribution<int> range(min, max);
int random_num = range(_mt);
random
<random>
c++11
mt19937은 메르센 트위스터 엔진을 사용하여 난수를 추출한다. 장치에서 얻어온 시드값을 통
해 메르센 소수를 이용하여 난수 시드를 재설정한다. 이제 난수생성 형식과 타입을 결정한다.
정수형 난수: std::uniform_int_distribution
실수형 난수: std::uniform_real_distribution 외에도 다양한 난수 분포가 존재한다.
std::random_device _random_device;
std::mt19937 _mt(_random_device());
std::uniform_int_distribution<int> range(min, max);
int random_num = range(_mt);
random
<random>
c++11
오른쪽의 default_random_engine를 사용하면 랜덤 장치에 기본이 메르센 트위스터 엔진으로
설정되어 있는 상태에서 난수를 발생한다.
std::random_device _random_device;
std::mt19937 _mt(_random_device());
std::uniform_int_distribution<int> range(min, max);
int random_num = range(_mt);
random
c++11
filesystem
c++17
C++11에서는 Boost 라이브러리가 있어야 사용할 수 있다.
C++14부터는 std::experimental::filesystem으로 사용할 수 있고 C++17부터 표준이 되었다.
네임스페이스가 길기 때문에 위와 같이 사용할 수 있다.
#include <filesystem>
namespace FILESYSTEM = std::experimental::filesystem;
filesystem
c++17
파일 시스템은 기본적으로 path변수에 생성자로 넣어준 경로로 부터 시작합니다.
FILESYSTEM::path find_file(“..ResourceMesh”);
filesystem
c++17
파일 시스템은 기본적으로 path변수에 생성자로 넣어준 경로로 부터 시작한다.
filesystem에 탑재된 is_directory 함수를 통하여 현재 경로가 폴더인지 확인할 수 있다
FILESYSTEM::path find_file(“..ResourceMesh”);
if(false == FILESYSTEM::is_directory(find_file)) return;
filesystem
c++17
FILESYSTEM::directory_iterator을 통해 폴더 내의 모든 파일에 대해 접근할 수 있는 반복자를
사용합니다. 범위 기반 for문을 통해 각 파일을 FILESYSTEM::directory_entry라는 폴더 내 항목
변수에 담는다.
FILESYSTEM::path find_file(“..ResourceMesh”);
for(const auto& directory : FILESYSTEM::directory_iterator(find_file))
{
(. . .)
}
filesystem
c++17
FILESYSTEM::is_regular_file 함수를 통해 현재 directory의 상태(경로의 파일 상태)가 일반 파일인지 확인한
다.
for(const auto& directory : FILESYSTEM::directory_iterator(find_file))
{
if(FILESYSTEM::is_regular_file(directory.status()) { (. . .) }
}
filesystem
c++17
directory의 멤버 함수 path()를 사용하여 현재 경로를 반환한다. 반환형은 FILESYSTEM::path이기 때문에
문자열 첫 번째 주소를 반환하는 c_str() 멤버 함수를 통해 경로의 문자열을 얻을 수 있다. string에 넣을 경우
대입연산자에 넣으면 된다.
for(const auto& directory : FILESYSTEM::directory_iterator(find_file))
{
char filepath[128] = “”;
strcmp(filepath, directory.path().c_str());
string filepath = directory.path();
}
filesystem
c++17
path의 멤버 함수 extension()을 호출하면 .을 포함한 확장자만 얻을 수 있다. 이 확장자 역시 path 변수로 나
오며 멤버 함수 compare를 통해 문자열 비교를 할 수 있다. strcmp와 동일하게 0이 나오면 같은 문자열이
다.
확장자를 검사하여 그 확장자 파일만 로드하도록 할 수 있다.
for(const auto& directory : FILESYSTEM::directory_iterator(find_file))
{
if(0 == directory.path().extension().compare(“.png”)) { (. . .) }
}
filesystem
c++17
path의 멤버 함수 stem()을 호출하면 현재 경로의 파일 또는 폴더명만 남기고 경로, 확장자를 제거한 path를
반환한다. map 등에 저장할 key값으로 주로 사용하였다.
for(const auto& directory : FILESYSTEM::directory_iterator(find_file))
{
string key = directory.path().stem();
}
filesystem
c++17
vector 접근 팁
vector에 원소에 접근하는데 가장 왼쪽과 같은 []연산자를 통한 접근은 매우 비효율적이다.
가장 오른쪽과 같이 벡터 배열의 첫 번째 주소를 받아온 다음 주소를 건너뛰는 방식을 사용하는 것이 성능을
향상시키는데 매우 도움이 된다.
속도는 오른쪽 > 중간 > 왼쪽 순으로 오른쪽이 가장 빠르다. 포인터 형식이 불편하면 반복자 또는 범위기반
을 이용하는것이 차선책이다.
vector<int> vec = { 1, 2, 3, 4, 5 };
for(size_t i = 0; i < vec.size(); ++i)
vec[i] = 0;
vector<int> vec = { 1, 2, 3, 4, 5 };
int* vec_first = &vec[0];
for(size_t i = 0; i < vec.size(); ++i)
(*vec_first + i) = 0;
vector<int> vec = { 1, 2, 3, 4, 5 };
auto iter = vec.begin();
auto iter = vec.end();
for( ; iter != iter_end; ++iter)
*iter = 0;
Q & A

More Related Content

What's hot

레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다Lee Dustin
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀승명 양
 
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기Woong won Lee
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기Seungjae Lee
 
Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식TonyCms
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019devCAT Studio, NEXON
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaqueLuciano Ramalho
 
[RLkorea] 각잡고 로봇팔 발표
[RLkorea] 각잡고 로봇팔 발표[RLkorea] 각잡고 로봇팔 발표
[RLkorea] 각잡고 로봇팔 발표ashley ryu
 
iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunFactory Inc.
 
C++20 Coroutine
C++20 CoroutineC++20 Coroutine
C++20 Coroutine진화 손
 
.NET 6 時代のデスクトップ アプリケーション開発
.NET 6 時代のデスクトップ アプリケーション開発.NET 6 時代のデスクトップ アプリケーション開発
.NET 6 時代のデスクトップ アプリケーション開発Fujio Kojima
 
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon Web Services Korea
 
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리강 민우
 
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4Amazon Web Services Korea
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017devCAT Studio, NEXON
 
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지Minjung Ko
 
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기Chanwoong Kim
 
AWS Lambda, Step Functions & MongoDB Atlas Tutorial
AWS Lambda, Step Functions & MongoDB Atlas TutorialAWS Lambda, Step Functions & MongoDB Atlas Tutorial
AWS Lambda, Step Functions & MongoDB Atlas TutorialMongoDB
 
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...Amazon Web Services Korea
 
[0602 박민근] Direct2D
[0602 박민근] Direct2D[0602 박민근] Direct2D
[0602 박민근] Direct2D흥배 최
 

What's hot (20)

레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀
 
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기
 
Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식Cpp에서 활용해보는 Lambda식
Cpp에서 활용해보는 Lambda식
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaque
 
[RLkorea] 각잡고 로봇팔 발표
[RLkorea] 각잡고 로봇팔 발표[RLkorea] 각잡고 로봇팔 발표
[RLkorea] 각잡고 로봇팔 발표
 
iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기
 
C++20 Coroutine
C++20 CoroutineC++20 Coroutine
C++20 Coroutine
 
.NET 6 時代のデスクトップ アプリケーション開発
.NET 6 時代のデスクトップ アプリケーション開発.NET 6 時代のデスクトップ アプリケーション開発
.NET 6 時代のデスクトップ アプリケーション開発
 
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon SageMaker 모델 배포 방법 소개::김대근, AI/ML 스페셜리스트 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
 
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
[IGC 2017] 블루홀 최준혁 - '플레이어언노운스 배틀그라운드' DEV 스토리
 
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
AWS로 게임 런칭 준비하기 ::: 장준성, 채민관, AWS Game Master 온라인 시리즈 #4
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
 
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지
[NDC2017] 뛰는 프로그래머 나는 언리얼 엔진 - 언알못에서 커미터까지
 
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
[NDC18] 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포 이야기
 
AWS Lambda, Step Functions & MongoDB Atlas Tutorial
AWS Lambda, Step Functions & MongoDB Atlas TutorialAWS Lambda, Step Functions & MongoDB Atlas Tutorial
AWS Lambda, Step Functions & MongoDB Atlas Tutorial
 
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...
[2017 Gaming on AWS] GameLift를 통한 실전 DevOps: 세션형 멀티플레이어 게임의 구현부터 운영까지 Step by...
 
[0602 박민근] Direct2D
[0602 박민근] Direct2D[0602 박민근] Direct2D
[0602 박민근] Direct2D
 

Similar to 포트폴리오에서 사용한 모던 C++

C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부Gwangwhi Mah
 
Modern C++의 타입 추론과 람다, 컨셉
Modern C++의 타입 추론과 람다, 컨셉Modern C++의 타입 추론과 람다, 컨셉
Modern C++의 타입 추론과 람다, 컨셉HyunJoon Park
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기지수 윤
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2Chris Ohk
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선daewon jeong
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌Seok-joon Yun
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린Park JoongSoo
 
[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features SummaryChris Ohk
 
Lambda 란 무엇인가
Lambda 란 무엇인가Lambda 란 무엇인가
Lambda 란 무엇인가Vong Sik Kong
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features SummaryChris Ohk
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 

Similar to 포트폴리오에서 사용한 모던 C++ (20)

C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부C++ 11 에 대해서 쉽게 알아봅시다 1부
C++ 11 에 대해서 쉽게 알아봅시다 1부
 
Changes in c++0x
Changes in c++0xChanges in c++0x
Changes in c++0x
 
Modern C++의 타입 추론과 람다, 컨셉
Modern C++의 타입 추론과 람다, 컨셉Modern C++의 타입 추론과 람다, 컨셉
Modern C++의 타입 추론과 람다, 컨셉
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 
W14 chap13
W14 chap13W14 chap13
W14 chap13
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2
 
06장 함수
06장 함수06장 함수
06장 함수
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
강의자료3
강의자료3강의자료3
강의자료3
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
6 function
6 function6 function
6 function
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린
 
[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary
 
Lambda 란 무엇인가
Lambda 란 무엇인가Lambda 란 무엇인가
Lambda 란 무엇인가
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features Summary
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 

More from KWANGIL KIM

210320 웹 통신
210320 웹 통신210320 웹 통신
210320 웹 통신KWANGIL KIM
 
191221 unreal engine 4 editor 확장하기
191221 unreal engine 4 editor 확장하기191221 unreal engine 4 editor 확장하기
191221 unreal engine 4 editor 확장하기KWANGIL KIM
 
191019 Forward / Deferred Rendering
191019 Forward / Deferred Rendering191019 Forward / Deferred Rendering
191019 Forward / Deferred RenderingKWANGIL KIM
 
190720 언리얼 서밋 2일차 리뷰
190720 언리얼 서밋 2일차 리뷰190720 언리얼 서밋 2일차 리뷰
190720 언리얼 서밋 2일차 리뷰KWANGIL KIM
 
181215 MS SQL로 알아보는 데이터베이스
181215 MS SQL로 알아보는 데이터베이스181215 MS SQL로 알아보는 데이터베이스
181215 MS SQL로 알아보는 데이터베이스KWANGIL KIM
 
OnePointLesson PriorityQueue 우선순위 큐
OnePointLesson PriorityQueue 우선순위 큐OnePointLesson PriorityQueue 우선순위 큐
OnePointLesson PriorityQueue 우선순위 큐KWANGIL KIM
 

More from KWANGIL KIM (6)

210320 웹 통신
210320 웹 통신210320 웹 통신
210320 웹 통신
 
191221 unreal engine 4 editor 확장하기
191221 unreal engine 4 editor 확장하기191221 unreal engine 4 editor 확장하기
191221 unreal engine 4 editor 확장하기
 
191019 Forward / Deferred Rendering
191019 Forward / Deferred Rendering191019 Forward / Deferred Rendering
191019 Forward / Deferred Rendering
 
190720 언리얼 서밋 2일차 리뷰
190720 언리얼 서밋 2일차 리뷰190720 언리얼 서밋 2일차 리뷰
190720 언리얼 서밋 2일차 리뷰
 
181215 MS SQL로 알아보는 데이터베이스
181215 MS SQL로 알아보는 데이터베이스181215 MS SQL로 알아보는 데이터베이스
181215 MS SQL로 알아보는 데이터베이스
 
OnePointLesson PriorityQueue 우선순위 큐
OnePointLesson PriorityQueue 우선순위 큐OnePointLesson PriorityQueue 우선순위 큐
OnePointLesson PriorityQueue 우선순위 큐
 

포트폴리오에서 사용한 모던 C++

  • 2. STL(Standard Template Library) C++에서 제공하는 자료구조, 알고리즘, 등을 사용하기 편하게 만든 표준 템플릿 라이브러리 std::vector, std::list, std::map, std::sort, std::for_each 등이 있다.
  • 3. 반복자(iterator) STL 컨테이너의 내부 요소를 순회하는 객체로 포인터와 유사하나 포인터와는 다르다. 1 2 3 4 5std::vector<int> vec std::vector<int>::iterator iter vec.begin() vec.end()
  • 4. auto 키워드 c++11 변수를 초기화하는 동시에 자료형을 추론해주는 키워드. 초기화를 하지 않을 경우 사용할 수 없다. auto num; // error auto num = 1; // int auto num = 1.f // float auto num = 1.0 // double
  • 5. auto 키워드 c++11 vector<int> vec; auto iter = vec.begin(); // vector<int>::iterator 위와 같이 긴 반복자 변수를 auto 키워드로 줄일 수 있다. auto func = []() { std::cout << “Func” }; // 함수 포인터 타입
  • 6. 범위 기반 for문 c++11 배열 또는 컨테이너에 접근하여 모든 원소를 순회하는 for문 일반 배열에서는 범위기반이 동작하지만 동적 배열에는 동작하지 않는다. int arr[10] = {} for(int i = 0; i < 10; ++i) std::cin >> arr[i]; int arr[10] = {} for(int num : arr) std::cin >> num;
  • 7. 범위 기반 for문 c++11 위와 같이 STL 컨테이너 순회에 응용할 수 있다. std::vector<int> vec(10, 0); auto iter = vec.begin(); auto iter_end = vec.end(); for( ; iter != iter_end; ++iter) std::cin >> *iter; std::vector<int> vec(10, 0); for(auto& num : vec) std::cin >> num; std::vector<int> vec(10, 0); for(size_t i = 0; i < vec.size(); ++i) std::cin >> vec[i];
  • 9. override 키워드 c++11 class Parent { virtual void Out() { std::cout << “Parent” << std::endl; }class Derived : public Parent { virtual void Out() override { std::cout << “Derived ” << std::endl; void MyOut() override; // error } 가상 함수를 자식 클래스에서 오버 라이딩 할 때 명시적으로 선언할 수 있다. 부모 클래스에서 선언되지 않은 함수를 명시적 으로 표기할 때 에러를 발생한다.
  • 11. Uniform 초기화 c++11 모든 오브젝트 타입에 대해 동일한 방식으로 리스트형 초기화를 할 수 있는 기능. int i = { 1 }; int arr[5] = { 1, 2, 3, 4, 5 }; std::vector<int> vec = { 1, 2, 3 }; struct Point { float a, float b; } Point pt = {};
  • 12. Uniform 초기화 c++11 class Vector3 { Vector3() {}; Vector3(float _x, float _y, float _z) { x = _x; y = _y; z = _z; } float x, y, z; } Vector3 player_position = {}; Vector3 enemy_position = { 5.f, 0.f, 10.f }; 다음과 같은 경우 player_position의 멤버 변수는 초기화 되 지 않음. 아무런 초기화도 하지 않는 생성자가 호출되었기 때문이다. enemy_position의 경우 Vector3(float _x, float _y, float _z) 생성자를 호출하여 Uniform 초기화를 수행. 클래스의 생성 형식을 유지하고 싶다면 explicit 키워드를 사 용하자.
  • 14. 명시적 기본 설정 및 삭제 c++11 Effective C++에서 복사가 일어나면 안되는 객체에 대하여 복사를 막는 방법으로 아래와 같이 복사생성자를 private로 하는 방법이 나와있다. class Player { private: Player(const Player& rhs); };
  • 15. 명시적 기본 설정 및 삭제 c++11 C++11 부터는 클래스를 작성하면 기본적으로 만들어주는 생성자, 복사 생성자, 대입연산자를 명시적으로 선언하거나 삭제할 수 있다. class Player { Player() = default; Player(const Player& rhs) = delete; };
  • 16. 명시적 기본 설정 및 삭제 c++11
  • 17. enum vs enum class c++11 enum ObjectTag { Player, Enemy, Environment, End }; enum ColliderTag { Enemy, Player, Environment, End }; std::list<CGameObject*> object_list_[End]; (o) std::list<CGameObject*> object_list_[ObjectTag::End]; (o) enum class ObjectTag { Player, Enemy, Environment, End }; enum class ColliderTag { Player, Enemy, Environment, End }; std::list<CGameObject*> object_list_[End]; (x) std::list<CGameObject*> object_list_[ObjectTag::End]; (x) C++에서는 enum의 값을 int 형태로 처리한다. 왼쪽과 같이 기존의 enum으로 선언할 경우 정적 배열의 enum 개수만큼 초기화 할 수 있다. 그리고 enum 타입을 생략하고 사용할 수 있다. 하지 만 ObjectTag 타입에 선언된 이름과 ColliderTag에 선언된 이름은 중복될 경우 타입을 명시적 으로 하지 않으면 ColliderTag의 값으로 인식한다.
  • 18. enum vs enum class c++11 enum ObjectTag { Player, Enemy, Environment, End }; enum ColliderTag { Enemy, Player, Environment, End }; std::list<CGameObject*> object_list_[End]; (o) std::list<CGameObject*> object_list_[ObjectTag::End]; (o) enum class ObjectTag { Player, Enemy, Environment, End }; enum class ColliderTag { Player, Enemy, Environment, End }; std::list<CGameObject*> object_list_[End]; (x) std::list<CGameObject*> object_list_[ObjectTag::End]; (x) 오른쪽의 enum class의 경우 명시적으로 enum 타입을 사용해야 열거형 값을 사용할 수 있다. 단 unsigned int로 인식은 하지만 enum 타입때문에 정적 배열에 사용할 수 없다.
  • 19. enum vs enum class c++11 C++에서는 enum의 값을 int로 처리한다.
  • 20. enum vs enum class c++11
  • 21. push_back vs emplace_back c++11 push_back의 경우 기존의 STL 컨테이너에 원소를 넣을 때 사용하는 함수이다. emplace_back는 C++11부터 추가된 STL 컨테이너에 원소를 넣을 때 사용하는 함수이다. 둘은 같은 역할을 한다. 하지만 차이점이 존재한다. std::vector<Object*> vec_object; vec_object.push_back(new Object); vec_object.emplace_back(new Object);
  • 22. push_back vs emplace_back c++11 int main() { std::vector<Object> vec; vec.reserve(100); std::cout << "push_back: " << std::endl; vec.push_back(5); std::cout << std::endl; std::cout << "emplace_back: " << std::endl; vec.emplace_back(5); std::cout << std::endl; return 0; } #include <iostream> #include <vector> class Object { public: Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; } Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자" << std::endl; } ~Object() { std::cout << "소멸자" << std::endl; } private: int hp = 0; }; 위 코드를 실행한다.
  • 23. push_back vs emplace_back c++11 int main() { std::vector<Object> vec; vec.reserve(100); std::cout << "push_back: " << std::endl; vec.push_back(5); std::cout << std::endl; std::cout << "emplace_back: " << std::endl; vec.emplace_back(5); std::cout << std::endl; return 0; } #include <iostream> #include <vector> class Object { public: Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; } Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자" << std::endl; } ~Object() { std::cout << "소멸자" << std::endl; } private: int hp = 0; }; 다음과 같은 결과를 나타낸다.
  • 24. push_back vs emplace_back c++11 int main() { std::vector<Object> vec; vec.reserve(100); std::cout << "push_back: " << std::endl; vec.push_back(5); std::cout << std::endl; std::cout << "emplace_back: " << std::endl; vec.emplace_back(5); std::cout << std::endl; return 0; } #include <iostream> #include <vector> class Object { public: Object(int _hp) : hp(_hp) { std::cout << "생성자" << std::endl; } Object(const Object& rhs) : hp(rhs.hp) { std::cout << "복사 생성자" << std::endl; } ~Object() { std::cout << "소멸자" << std::endl; } private: int hp = 0; }; push_back과 emplace_back는 각각 &&(R-Value Reference)를 받는 함수로 오버로딩 되어있다. 이때 push_back의 경우 임시 객체를 생성하고 vector에 삽입 후 삭제까지한다. 반면 emplace_back의 경우 원소의 그 위치에 바로 생성하는 형태이다.
  • 25. push_back vs emplace_back c++11 중간에 원소를 삽입하는 Insert와 같은 역할을 하는 emplace 함수도 있다. vector는 emplace_back, emplace list는 emplace_front, emplace_back, emplace map은 emplace 함수가 각각 구현되어있다.
  • 26. R-Value Reference c++11 int num = 1; L-Value R-Value 먼저 L-Value와 R-Value를 알아본다. 위 변수와 같이 왼쪽에 있는 값이 L-Value, 오른쪽에 있는 값이 R-Value이다.
  • 27. R-Value Reference c++11 int num = 1; L-Value R-Value 보통 왼쪽에는 변수를 선언할 것이고 오른쪽에는 다른 변수를 대입하거나 임의의 상수 또는 임시 객체 등을 사용할 것이다. 이때 임의의 상수 리터럴 변수와 임시 객체 등은 R-Value이다.
  • 28. R-Value Reference c++11 int num = 1; int num2 = num; 위 상태의 경우 num은 오른쪽에 있지만 L-Value 이다.
  • 29. R-Value Reference c++11 int num = 5; int 1 = num; (Error) R-Value를 조금 더 쉽게 구분하자면 왼쪽에 올 수 없는 값(리터럴, 임시 객체 등은 왼쪽에 올 수 없 다)을 R-Value라고 생각하면 될 것이다. class A {}; A a; A() = a; (Error)
  • 30. R-Value Reference c++11 리터럴 상수 5를 num이라는 R-Value Reference에 초기화 하였다. 기존의 레퍼런스는 위와 같이 리터럴 상수 또는 임시 객체를 담을 수 없다. int& r_num = 5; (Error) int&& num = 5; class A {}; A& a = A(); (Error) A&& a = A();
  • 31. Lambda c++11 람다식은 무명 함수(이름 없는 함수)라고 부른다. 이름 그대로 함수의 이름이 존재하지 않는 함수이다. [&](int a) -> int { return a; } [ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
  • 32. Lambda c++11 람다식 구현부에서는 람다식 외부의 변수 또는 함수를 사용할 수 없다. 이때 캡처절을 이용하여 외부 지역의 변수 또는 클래스의 멤버 함수를 가져와서 사용할 수 있다. [&](int a) -> int { return a; } [ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
  • 33. Lambda c++11 []: 공백일 때에는 아무 것도 캡처하지 않는 상태이다. [=]: 외부 지역의 모든 변수와 클래스의 경우 멤버 함수 주소까지 값(Call by Value)으로 캡처한다. [&]: 외부 지역의 모든 변수와 클래스의 경우 멤버 함수 주소까지 레퍼런스(Call by Reference)로 캡처한다. [x]: 외부 지역의 변수 x를 값으로 캡처한다. [&x]: 외부 지역의 변수 레퍼런스로 캡처한다. [&](int a) -> int { return a; } [ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
  • 34. Lambda c++11 [x, &]: x만 값으로 그 외에는 레퍼런스로 캡처한다. [&x, =]: x만 레퍼런스로 그 외에는 값으로 캡처한다. [x, &y]: x는 값으로, y는 레퍼런스로 캡처한다. [&](int a) -> int { return a; } [ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
  • 35. Lambda c++11 그 외에 매개변수절은 기존 함수와 동일하고 반환형의 경우 명시적으로 선언할 수 있고 따로 명 시하지 않아도 return 값에 따라 반환 타입을 결정해준다. 구현부에는 함수의 내용을 구현하면 된다. [&](int a) -> int { return a; } [ 캡처절 ] ( 매개변수 ) -> 반환형 { 구현부 }
  • 36. Lambda c++11 다음과 같이 STL 알고리즘 함수에 임의의 조건자를 넣을 때 람다식으로 만들어서 넣을 수 있다. 함수자 또는 함수객체를 대체할 수 있으며 함수 객체의 장점인 멤버 변수를 가질 수 있는 부분 을 캡처절을 활용하여 대체할 수 있다.
  • 37. std::function <functional> c++11 함수 포인터를 유연하게 사용하기 위한 변수. 함수 포인터의 경우 람다, 함수 객체를 담을 수 없 다. C++11 부터는 유연성이 강한 함수를 담을 수 있는 변수를 제공한다. std::function<void()> func = []()->void { std::cout << “Hello World” << std::endl; }; std::function<int(int)> func = [](int a)->int { return a; };
  • 39. random <random> c++11 seed값을 통하여 난수를 반환하는 rand 함수는 매우 한계가 크다. C++11부터는 random 클래스를 제공하여 좀 더 확실한 난수를 얻을 수 있다. random_device를 이용하면 하드웨어의 리소스를 사용하여 시드를 설정하여 랜덤값을 가져온 다. std::random_device _random_device; std::mt19937 _mt(_random_device()); std::uniform_int_distribution<int> range(min, max); int random_num = range(_mt);
  • 40. random <random> c++11 mt19937은 메르센 트위스터 엔진을 사용하여 난수를 추출한다. 장치에서 얻어온 시드값을 통 해 메르센 소수를 이용하여 난수 시드를 재설정한다. 이제 난수생성 형식과 타입을 결정한다. 정수형 난수: std::uniform_int_distribution 실수형 난수: std::uniform_real_distribution 외에도 다양한 난수 분포가 존재한다. std::random_device _random_device; std::mt19937 _mt(_random_device()); std::uniform_int_distribution<int> range(min, max); int random_num = range(_mt);
  • 41. random <random> c++11 오른쪽의 default_random_engine를 사용하면 랜덤 장치에 기본이 메르센 트위스터 엔진으로 설정되어 있는 상태에서 난수를 발생한다. std::random_device _random_device; std::mt19937 _mt(_random_device()); std::uniform_int_distribution<int> range(min, max); int random_num = range(_mt);
  • 43. filesystem c++17 C++11에서는 Boost 라이브러리가 있어야 사용할 수 있다. C++14부터는 std::experimental::filesystem으로 사용할 수 있고 C++17부터 표준이 되었다. 네임스페이스가 길기 때문에 위와 같이 사용할 수 있다. #include <filesystem> namespace FILESYSTEM = std::experimental::filesystem;
  • 44. filesystem c++17 파일 시스템은 기본적으로 path변수에 생성자로 넣어준 경로로 부터 시작합니다. FILESYSTEM::path find_file(“..ResourceMesh”);
  • 45. filesystem c++17 파일 시스템은 기본적으로 path변수에 생성자로 넣어준 경로로 부터 시작한다. filesystem에 탑재된 is_directory 함수를 통하여 현재 경로가 폴더인지 확인할 수 있다 FILESYSTEM::path find_file(“..ResourceMesh”); if(false == FILESYSTEM::is_directory(find_file)) return;
  • 46. filesystem c++17 FILESYSTEM::directory_iterator을 통해 폴더 내의 모든 파일에 대해 접근할 수 있는 반복자를 사용합니다. 범위 기반 for문을 통해 각 파일을 FILESYSTEM::directory_entry라는 폴더 내 항목 변수에 담는다. FILESYSTEM::path find_file(“..ResourceMesh”); for(const auto& directory : FILESYSTEM::directory_iterator(find_file)) { (. . .) }
  • 47. filesystem c++17 FILESYSTEM::is_regular_file 함수를 통해 현재 directory의 상태(경로의 파일 상태)가 일반 파일인지 확인한 다. for(const auto& directory : FILESYSTEM::directory_iterator(find_file)) { if(FILESYSTEM::is_regular_file(directory.status()) { (. . .) } }
  • 48. filesystem c++17 directory의 멤버 함수 path()를 사용하여 현재 경로를 반환한다. 반환형은 FILESYSTEM::path이기 때문에 문자열 첫 번째 주소를 반환하는 c_str() 멤버 함수를 통해 경로의 문자열을 얻을 수 있다. string에 넣을 경우 대입연산자에 넣으면 된다. for(const auto& directory : FILESYSTEM::directory_iterator(find_file)) { char filepath[128] = “”; strcmp(filepath, directory.path().c_str()); string filepath = directory.path(); }
  • 49. filesystem c++17 path의 멤버 함수 extension()을 호출하면 .을 포함한 확장자만 얻을 수 있다. 이 확장자 역시 path 변수로 나 오며 멤버 함수 compare를 통해 문자열 비교를 할 수 있다. strcmp와 동일하게 0이 나오면 같은 문자열이 다. 확장자를 검사하여 그 확장자 파일만 로드하도록 할 수 있다. for(const auto& directory : FILESYSTEM::directory_iterator(find_file)) { if(0 == directory.path().extension().compare(“.png”)) { (. . .) } }
  • 50. filesystem c++17 path의 멤버 함수 stem()을 호출하면 현재 경로의 파일 또는 폴더명만 남기고 경로, 확장자를 제거한 path를 반환한다. map 등에 저장할 key값으로 주로 사용하였다. for(const auto& directory : FILESYSTEM::directory_iterator(find_file)) { string key = directory.path().stem(); }
  • 52. vector 접근 팁 vector에 원소에 접근하는데 가장 왼쪽과 같은 []연산자를 통한 접근은 매우 비효율적이다. 가장 오른쪽과 같이 벡터 배열의 첫 번째 주소를 받아온 다음 주소를 건너뛰는 방식을 사용하는 것이 성능을 향상시키는데 매우 도움이 된다. 속도는 오른쪽 > 중간 > 왼쪽 순으로 오른쪽이 가장 빠르다. 포인터 형식이 불편하면 반복자 또는 범위기반 을 이용하는것이 차선책이다. vector<int> vec = { 1, 2, 3, 4, 5 }; for(size_t i = 0; i < vec.size(); ++i) vec[i] = 0; vector<int> vec = { 1, 2, 3, 4, 5 }; int* vec_first = &vec[0]; for(size_t i = 0; i < vec.size(); ++i) (*vec_first + i) = 0; vector<int> vec = { 1, 2, 3, 4, 5 }; auto iter = vec.begin(); auto iter = vec.end(); for( ; iter != iter_end; ++iter) *iter = 0;
  • 53. Q & A