79
옥찬호 / 넥슨 (NEXON KOREA), Visual C++ MVP 녹슨 C++ 코드에 모던 C++로 기름칠하기

[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

Embed Size (px)

Citation preview

Page 1: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

옥찬호 / 넥슨 (NEXON KOREA), Visual C++ MVP

녹슨 C++ 코드에 모던 C++로 기름칠하기

Page 2: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

시작하기 전에…

• 모던 C++이란 C++11/14를 말합니다.

• C++11/14을 통한 개선 뿐만 아니라

기존 C++을 통한 개선 방법도 함께 포함합니다.

• 모던 C++을 모르는 분들을 위해 최대한 쉽게 설명합니다.

• 예제 코드가 많은 부분을 차지합니다.

Page 3: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

녹슨 C++ 코드란?

Page 4: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

int _output(FILE* stream,char const* format,va_list arguments)

{// ...

}

Page 5: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#ifdef _UNICODEint _woutput (#else /* _UNICODE */int _output (#endif /* _UNICODE */

FILE* stream,_TCHAR const* format,va_list arguments)

{// ...

}

Page 6: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#ifdef _UNICODE#ifdef POSITIONAL_PARAMETERSint _woutput_p (#else /* POSITIONAL_PARAMETERS */int _woutput (#endif /* POSITIONAL_PARAMETERS */#else /* _UNICODE */#ifdef POSITIONAL_PARAMETERSint _output_p (#else /* POSITIONAL_PARAMETERS */int _output (#endif /* POSITIONAL_PARAMETERS */#endif /* _UNICODE */

FILE* stream,_TCHAR const* format,va_list arguments)

{ ... }

Page 7: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

IFileDialog *pfd = NULL;HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pfd));if (SUCCEEDED(hr)) {

IFileDialogEvents *pfde = NULL;hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));if (SUCCEEDED(hr)) {

DWORD dwCookie;hr = pfd->Advise(pfde, &dwCookie);if (SUCCEEDED(hr)) {

DWORD dwFlags;hr = pfd->GetOptions(&dwFlags);if (SUCCEEDED(hr)) {

hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);if (SUCCEEDED(hr)) {

hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);if (SUCCEEDED(hr)) {

hr = pfd->SetFileTypeIndex(INDEX_WORDDOC);if (SUCCEEDED(hr)) {

hr = pfd->SetDefaultExtension(L"doc;docx");if (SUCCEEDED(hr)) {

Page 8: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
Page 9: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

고치고 싶다… 하지만

• 이미 고치기엔 길어져버린 코드

• 어디서부터 손을 써야 할 지 모름

• 코드는 점점 산으로…

• 아 귀찮다… ㅁㄴㅇㄹ

Page 10: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
Page 11: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

어디에 기름칠을 해볼까?

• 전처리기

• 리소스 관리

• 함수

• 타입, 반복문

• 기타 등등…

Page 12: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

전처리기

Page 13: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

조건부 컴파일

• #if, #ifdef, #ifndef, #elif, #else, …

• 많이 쓸수록 복잡해진다.

• 많이 쓸수록 이해하기 어렵다.

• 많이 쓸수록 유지보수하기 어렵다.

Page 14: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#ifdef _UNICODEint _woutput (#else /* _UNICODE */int _output (#endif /* _UNICODE */

FILE* stream,_TCHAR const* format,va_list arguments)

{// ...

}

Page 15: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

template <typename T>static int common_output(

FILE* stream,T const* format,va_list arguments)

{// ...

}

int _output(FILE* stream, char const* format, va_list const arguments) {return common_output(stream, format, arguments);

}

int _woutput(FILE* stream, wchar_t const* format, va_list const arguments) {return common_output(stream, format, arguments);

}

Page 16: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

// Check windows#if _WIN32 || _WIN64#if _WIN64#define ENVIRONMENT64#else#define ENVIRONMENT32#endif#endif

// Check GCC#if __GNUC__#if __x86_64__ || __ppc64__#define ENVIRONMENT64#else#define ENVIRONMENT32#endif#endif

Page 17: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

케이스 바이 케이스

• 타입에 따른 조건부 컴파일은 함수 템플릿을 통해 개선한다.

• 하지만 #ifdef를 사용해야 되는 경우도 있다.

• 32비트 vs 64비트 코드

• DEBUG 모드 vs Non-DEBUG 모드

• 컴파일러, 플랫폼, 언어에 따라 다른 코드

• 반드시 사용해야 된다면, 코드를 단순화하는 것이 좋다.

• 중첩 #ifdef를 피하고, 함수의 일부를 조건부 컴파일에 넣지 않도록 한다.

Page 18: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

매크로

• #define …

• 변수 대신 사용하는 매크로 : #define RED 1

• 함수 대신 사용하는 매크로 : #define SQUARE(x) ((x) * (x))

• 수많은 문제를 일으키는 장본인

• 컴파일러가 타입에 대한 정보를 갖기 전에 계산됨

• 필요 이상으로 많이 사용

Page 19: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

변수 대신 사용하는 매크로

Page 20: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#define red 0#define orange 1#define yellow 2#define green 3#define blue 4#define purple 5#define hot_pink 6

void f(){

unsigned orange = 0xff9900;}

warning C4091: '' : ignored on left of 'unsigned int' when no variable is declarederror C2143: syntax error : missing ';' before 'constant'error C2106: '=' : left operand must be l-value

Page 21: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#define red 0#define orange 1#define yellow 2#define green 3#define blue 4#define purple 5#define hot_pink 6

void f(){

unsigned 2 = 0xff00ff;}

warning C4091: '' : ignored on left of 'unsigned int' when no variable is declarederror C2143: syntax error : missing ';' before 'constant'error C2106: '=' : left operand must be l-value

Page 22: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#define RED 0#define ORANGE 1#define YELLOW 2#define GREEN 3#define BLUE 4#define PURPLE 5#define HOT_PINK 6

void g(int color); // valid values are 0 through 6

void f(){

g(HOT_PINK); // Okg(9000); // Not ok, but compiler can’t tell

}

Page 23: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum color_type{

red = 0,orange = 1,yellow = 2,green = 3,blue = 4,purple = 5,hot_pink = 6

};

Page 24: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum color_type{

red, orange, yellow, green, blue, purple, hot_pink};

void g(color_type color);void f(){

g(hot_pink); // Okg(9000); // Not ok, compiler will report error

}

error C2664: 'void g(color_type)' : cannot convert argument 1 from 'int' to 'color_type'

Page 25: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum color_type{

red, orange, yellow, green, blue, purple, hot_pink};

void f(){

int x = red; // Ughint x = red + orange; // Double ugh

}

Page 26: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum color_type{

red, orange, yellow, green, blue, purple, hot_pink};

enum traffic_light_state{

red, yellow, green};

error C2365: 'red' : redefinition; previous definition was 'enumerator‘error C2365: 'yellow' : redefinition; previous definition was 'enumerator‘error C2365: 'green' : redefinition; previous definition was 'enumerator'

Page 27: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

열거체의 문제점

• 묵시적인 int 변환

• 열거체의 타입을 명시하지 못함

• 이상한 범위 적용

→ 열거체 클래스(enum class)의 등장!

Page 28: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum class color_type{

red, orange, yellow, green, blue, purple, hot_pink};

void g(color_type color);

void f(){

g(color_type::red);}

Page 29: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum class color_type{

red, orange, yellow, green, blue, purple, hot_pink};

void g(color_type color);

void f(){

int x = color_type::hot_pink;}

error C2440: 'initializing' : cannot convert from 'color_type' to 'int'

Page 30: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

enum class color_type{

red, orange, yellow, green, blue, purple, hot_pink};

void g(color_type color);

void f(){

int x = static_cast<int>(color_type::hot_pink);}

Page 31: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

열거체 클래스를 사용하자

• 묵시적인 int 변환

→ 명시적인 int 변환

• 열거체의 타입을 명시하지 못함

→ 타입 명시 가능

• 이상한 범위 적용

→ 범위 지정 연산자를 통해 구분

Page 32: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

함수 대신 사용하는 매크로

Page 33: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#define make_char_lowercase(c) \((c) = (((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))

void make_string_lowercase(char* s){

while (make_char_lowercase(*s++));

}

Page 34: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#define make_char_lowercase(c) \((c) = (((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))

void make_string_lowercase(char* s){

while (((*s++) = (((*s++) >= 'A') && ((*s++) <= 'Z'))? ((*s++) - 'A' + 'a') : (*s++)))

;}

Page 35: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

// Old, ugly macro implementation:#define make_char_lowercase(c) \

((c) = (((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))

// New, better function implementation:inline char make_char_lowercase(char& c){

if (c > 'A' && c < 'Z'){

c = c - 'A' + 'a';}

return c;}

Page 36: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

열거체, 함수를 사용하자

• 변수 대신 사용하는 매크로에는 열거체를 사용하자.

• 열거체에서 발생할 수 있는 문제는 enum class로 해결할 수 있다.

• 열거체 대신 ‘static const’ 변수를 사용하는 방법도 있다.

• 함수 대신 사용하는 매크로에는 함수를 사용하자.

• 읽기 쉽고, 유지보수하기 쉽고, 디버깅하기 쉽다.

• 성능에 따른 오버헤드도 없다.

Page 37: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

리소스 관리

Page 38: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

IFileDialog *pfd = NULL;HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pfd));if (SUCCEEDED(hr)) {

IFileDialogEvents *pfde = NULL;hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));if (SUCCEEDED(hr)) {

DWORD dwCookie;hr = pfd->Advise(pfde, &dwCookie);if (SUCCEEDED(hr)) {

DWORD dwFlags;hr = pfd->GetOptions(&dwFlags);if (SUCCEEDED(hr)) {

hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);if (SUCCEEDED(hr)) {

hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);if (SUCCEEDED(hr)) {

hr = pfd->SetFileTypeIndex(INDEX_WORDDOC);if (SUCCEEDED(hr)) {

hr = pfd->SetDefaultExtension(L"doc;docx");if (SUCCEEDED(hr)) {

Page 39: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

IFileDialog *pfd = NULL;HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, IID_PPV_ARGS(&pfd));if (FAILED(hr))

return hr;

IFileDialogEvents *pfde = NULL;hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));if (FAILED(hr))

return hr;

DWORD dwCookie;hr = pfd->Advise(pfde, &dwCookie);if (FAILED(hr))

return hr;

DWORD dwFlags;hr = pfd->GetOptions(&dwFlags);if (FAILED(hr))

return hr;

Page 40: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

}psiResult->Release();

}}

}}

}}

}pfd->Unadvise(dwCookie);

}pfde->Release();

}pfd->Release();

}

return hr;

\

Page 41: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

void ExampleWithoutRAII() {std::FILE* file_handle = std::fopen("logfile.txt", "w+");if (file_handle == nullptr)

throw std::runtime_error("File couldn't open!");

try {if (std::fputs("Hello, Log File!", file_handle) == EOF)

throw std::runtime_error("File couldn't write!");

// continue writing to logfile.txt ... do not return// prematurely, as cleanup happens at the end of this function

}catch (...){

std::fclose(file_handle);throw;

}

std::fclose(file_handle);}

\

Page 42: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

RAII

• 자원 획득은 초기화다 (Resource Acquisition Is Initialization)

• 객체의 생성에 맞춰 메모리와 시스템 리소스를 자동으로 할당

• 객체의 소멸에 맞춰 메모리와 시스템 리소스를 자동으로 해제

→ 생성자 안에서 리소스를 할당하고, 소멸자에서 리소스를 해제

Page 43: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

void ExampleWithRAII(){

// open file (acquire resource)File logFile("logfile.txt");

logFile.Write("Hello, Log File!");

// continue writing to logfile.txt ...}

File::File(const char* filename): m_file_handle(std::fopen(filename, "w+"))

{if (m_file_handle == NULL)

throw openError();}

File::~File(){

std::fclose(m_file_handle);}

Page 44: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

void ExampleWithRAII(){

// open file (acquire resource)File* logFile = new File("logfile.txt");

logFile->Write("Hello, Log File!");

// continue writing to logfile.txt ...}

File::File(const char* filename): m_file_handle(std::fopen(filename, "w+"))

{if (m_file_handle == NULL)

throw openError();}

File::~File(){

std::fclose(m_file_handle);}

Page 45: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

다시 발생하는 문제

• 파일 입출력과 관련한 예외 처리를 간편하게 하기 위해

File 클래스를 만들어 생성자와 소멸자로 처리했다.

• 하지만, 정작 File 클래스를 동적으로 할당하는 경우

소멸자가 호출되지 않아 파일을 닫지 않는 문제가 발생한다.

• 좋은 방법이 없을까?

→ 스마트 포인터(Smart Pointer)의 등장!

Page 46: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

스마트 포인터

• 좀 더 똑똑한 포인터

• 스마트 포인터를 사용하면 명시적으로 해제할 필요가 없다.

• 사용하는 이유

• 적은 버그, 자동 청소, 자동 초기화

• Dangling 포인터 발생 X, Exception 안전

• 효율성

Page 47: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

void ExampleWithRAII(){

// open file (acquire resource)std::unique_ptr<File> logFile = std::make_unique<File>("logfile.txt");

logFile->Write("Hello, Log File!");

// continue writing to logfile.txt ...}

File::File(const char* filename): m_file_handle(std::fopen(filename, "w+"))

{if (m_file_handle == NULL)

throw openError();}

File::~File(){

std::fclose(m_file_handle);}

Page 48: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

스마트 포인터의 종류

• 경우에 따라 여러 종류의 스마트 포인터를 사용할 수 있다.

• shared_ptr : 객체의 소유권을 복사할 수 있는 포인터

(여러 shared_ptr 객체가 같은 포인터 객체를 가리킬 수 있음)

• unique_ptr : 객체의 소유권을 복사할 수 없는 포인터

(하나의 unique_ptr 객체만이 하나의 포인터 객체를 가리킬 수 있음)

Page 49: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

std::unique_ptr

ptrA Song 개체

ptrA Song 개체

ptrB

auto ptrA = std::make_unique<Song>(L"Diana Krall", L"The Look of Love");

auto ptrB = std::move(ptrA);

Page 50: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

std::unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring& title){

// Implicit move operation into the variable that stores the result.return std::make_unique<Song>(artist, title);

}

void MakeSongs(){

// Create a new unique_ptr with a new object.auto song = std::make_unique<Song>(L"Mr. Children", L"Namonaki Uta");

// Use the unique_ptr.std::vector<std::wstring> titles = { song->title };

// Move raw pointer from one unique_ptr to another.std::unique_ptr<Song> song2 = std::move(song);

// Obtain unique_ptr from function that returns by value.auto song3 = SongFactory(L"Michael Jackson", L"Beat It");

}

Page 51: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

std::shared_ptr

MyClass

제어 블록 참조 개수 = 1

개체에 대한 포인터

제어 블록에 대한 포인터

p1

Page 52: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

std::shared_ptr

MyClass

제어 블록 참조 개수 = 2

개체에 대한 포인터

제어 블록에 대한 포인터

p1

개체에 대한 포인터

제어 블록에 대한 포인터

p2

Page 53: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

// Use make_shared function when possible.auto sp1 = std::make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");

// Ok, but slightly less efficient. // Note: Using new expression as constructor argument// creates no named variable for other code to access.std::shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));

// When initialization must be separate from declaration, e.g. class members, // initialize with nullptr to make your programming intent explicit.std::shared_ptr<Song> sp5(nullptr);//Equivalent to: shared_ptr<Song> sp5;//...sp5 = std::make_shared<Song>(L"Elton John", L"I'm Still Standing");

Page 54: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

리소스 관리는 스마트 포인터로

• RAII를 사용하자!

• 읽고, 쓰고, 유지보수하기 쉽다.

• 자원 관리에 대한 걱정을 할 필요가 없다.

• C++ 코드 품질을 향상시키는 가장 쉬운 방법!

• 기왕이면 스마트 포인터로!

• shared_ptr

• unique_ptr

Page 55: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

함수

Page 56: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

std::vector<int>::const_iterator iter = cardinal.begin();std::vector<int>::const_iterator iter_end = cardinal.end();

int total_elements = 1;while (iter != iter_end){

total_elements *= *iter;++iter;

}

Page 57: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

template <typename T>struct product {

product(T& storage) : value(storage) {}template<typename V>void operator()(V& v){

value *= v;}T& value;

};

std::vector<int> cardinal;

int total_elements = 1;for_each(cardinal.begin(), cardinal.end(), product<int>(total_elements));

Page 58: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

int total_elements = 1;for_each(cardinal.begin(), cardinal.end(), [&total_elements](int i) {

total_elements *= i;});

Page 59: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

struct mod

{

mod(int m) : modulus(m) {}

int operator()(int v)

{ return v % modulus; }

int modulus;

};

int my_mod = 8;

std::transform(in.begin(), in.end(),

out.begin(), mod(my_mod));

int my_mod = 8;

transform(in.begin(), in.end(), out.begin(),

[my_mod](int v) -> int

{ return v % my_mod; });

Functor Lambda Expression

Page 60: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

람다식

[my_mod] (int v) -> int { return v % my_mod; }

개시자(Introducer Capture)

인자(Arguments)

반환 타입(Return Type)

함수의 몸통(Statement)

Page 61: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

int x = 10, y = 20;

[] {}; // capture 하지 않음

[x] (int arg) { return x; }; // value(Copy) capture x

[=] { return x; }; // value(Copy) capture all

[&] { return y; }; // reference capture all

[&, x] { return y; }; // reference capture all except x

[=, &y] { return x; }; // value(Copy) capture all except y

[this] { return this->something; }; // this capture

[=, x] {}; // error

[&, &x] {}; // error

[=, this] {}; // error

[x, x] {}; // error

Page 62: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

1

2

2

void fa(int x, function<void(void)> f) { ++x; f(); }

void fb(int x, function<void(int)> f) { ++x; f(x); }

void fc(int &x, function<void(void)> f) { ++x; f(); }

int x = 1;

fa(x, [x] { cout << x << endl; });

fb(x, [](int x) { cout << x << endl; });

fc(x, [&x] { cout << x << endl; });

Page 63: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

WNDCLASSEX wcex;

wcex.lpfnWndProc= [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ->

LRESULT {

switch (message) {

case WM_COMMAND:

EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL {

char szText[256];

GetWindowTextA(hwnd, szText, 256);

cout << szText << endl;

return TRUE;

}, 0);

Page 64: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

HANDLE hT = CreateThread(NULL, 0, [](LPVOID lpThreadParameter) -> DWORD {

for (int i = 0; i < 1000; i++) {

this_thread::sleep_for(milliseconds{ 10 });

cout << i << endl;

}

return 0;

}, NULL, 0, NULL);

Page 65: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

람다식을 사용하자

• 짧고, 간결하고, while 문과 같은 행사 코드 없이

깔끔하게 작성할 수 있다.

• 수십줄의 코드를 1~2줄로 간추릴 수 있다.

• Functor, Callback Function을 대체해서 사용할 수 있다.

• 반복적으로 사용하는 함수가 아니라면 람다식을 사용하자!

Page 66: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

간단하게 적용 가능한 기능들

Page 67: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

auto 키워드

• 컴파일 타임에 타입을 추론해 어떤 타입인지 결정한다.

• 컴파일 타임에 추론이 불가능하다면, 오류가 발생한다.

std::vector<std::tuple<std::string, int, double>> vStudents;for (std::vector<std::tuple<std::string, int, double>>::iterator iter =

vStudents.begin(); iter != vStudents.end(); ++iter) { … }

std::vector<std::tuple<std::string, int, double>> vStudents;for (auto iter = vStudents.begin(); iter != vStudents.end(); ++iter) { … }

Page 68: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

범위 기반 for문

int arr[] = { 1, 2, 3, 4, 5 };

for (int i = 0; i < 5; ++i)std::cout << arr[i] << std::endl;

return 0;}

int arr[] = { 1, 2, 3, 4, 5 };

for (auto& i : arr)std::cout << i << std::endl;

return 0;}

Page 69: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

정리// circle and shape are user-defined typescircle* p = new circle(42);vector<shape*> v = load_shapes();

for (vector<circle*>::iterator i = v.begin(); i != v.end(); ++i) {if (*i && **i == *p)cout << **i << " is a match\n";

}

for (vector<circle*>::iterator i = v.begin(); i != v.end(); ++i) {delete *i; // not exception safe

}

delete p;

Page 70: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

정리// circle and shape are user-defined typesauto p = make_shared<circle>(42);vector<shared_ptr<shape>> v = load_shapes();

for_each(begin(v), end(v), [&](const shared_ptr<shape>& s) {if (s && *s == *p)

cout << *s << " is a match\n";});

Page 71: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

정리

• 대체할 수 있는 조건부 컴파일은 템플릿으로 기름칠!

• 매크로는 가급적 사용하지 말고 열거체와 함수로 기름칠!

• 리소스 관리에는 RAII, 기왕이면 스마트 포인터로 기름칠!

• 일회성으로 사용하는 함수는 람다식으로 기름칠!

• 복잡한 타입에는 auto로 기름칠!

• 반복 횟수에 고통받지 말고 범위 기반 for문으로 기름칠!

Page 72: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

정리

• 모던 C++을 통해 대체할 수 있는 코드는 많습니다!

(하지만 제한된 시간으로 인해 …)

• 다음 사이트에서 모던 C++ 예제 코드를 확인하실 수 있습니다.

http://www.github.com/utilForever/ModernCpp

• C++ 핵심 가이드라인

• 영문 : https://github.com/isocpp/CppCoreGuidelines

• 한글 : https://github.com/CppKorea/CppCoreGuidelines

Page 73: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

Quiz

Page 74: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#include <iostream>#include <memory>#include <vector>

class C {public:

void foo() { std::cout << "A"; }void foo() const { std::cout << "B"; }

};

struct S {std::vector<C> v;std::unique_ptr<C> u;C* const p;

S() : v(1), u(new C()), p(u.get()) {}};

Quiz #1int main() {

S s;const S& r = s;

s.v[0].foo(); s.u->foo(); s.p->foo();r.v[0].foo(); r.u->foo(); r.p->foo();

}

AAABAA

Page 75: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#include <iostream>

struct A {A() { std::cout << "A"; }A(const A& a) { std::cout << "B"; }virtual void f() { std::cout << "C"; }

};

int main() {A a[2];for (auto x : a) {

x.f();}

}

Quiz #2

AABCBC

Page 76: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

#include <iostream>

struct A {A() { std::cout << "A"; }A(const A& a) { std::cout << "B"; }virtual void f() { std::cout << "C"; }

};

int main() {A a[2];for (auto& x : a) {

x.f();}

}

Quiz #3

AACC

Page 77: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

C++ Korea

• http://www.facebook.com/groups/cppkorea

http://www.github.com/cppkorea

Page 78: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

감사합니다.• MSDN Forum http://aka.ms/msdnforum

• TechNet Forum http://aka.ms/technetforum

Page 79: [Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)

http://aka.ms/td2015_again

TechDays Korea 2015에서 놓치신 세션은 Microsoft 기술 동영상 커뮤니티 Channel 9에서

추후에 다시 보실 수 있습니다.