์์ฑ์ : ๋ฐ์ฌ์ฉ
๋ณธ ์๋ฃ๋ ์์ฑ์์ธ '๋ฐ์ฌ์ฉ'์ ๊ฐ์ธ Repository์ ๊ธ๊ณผ Effective Modern C++ ์ฑ ์ ์ฌ๊ตฌ์ฑํ์ฌ ์์ฑ๋์์ต๋๋ค.
Table of Contents
C++98(C++03) ๋ฒ์ ์ดํ ์ต์ ์ ํ์ ๋ง๊ฒ ์๋ก์ด C++ ํ์ค ๋ฌธ์๊ฐ ์ ๋ฐ์ดํธ๋์๊ณ ๊ตฌ ๋ฒ์ ์ C++98 ๊ธฐ๋ฅ๋ณด๋ค ์ฑ๋ฅ์ ํฅ์์ํฌ๋ฟ๋ง ์๋๋ผ ๊ฐ๋ ์ฑ, ์ฝ๋์ ๊ฐ๊ฒฐํจ๋ ์ฅ์ ์ผ๋ก ๋ ์ค๋ฅด๋ ์๋ก์ด C++ ๊ธฐ๋ฅ ์งํฉ ํ์คํ์ด๋ค.
Auto๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ์๋ฅผ ์ ์ธํ๊ฒ ๋๋ฉด ํน์ ์๋ฃํ์ ์ง์ ํ์ง ์์ ์ ์๋ค. auto๋ ์ฝ๋๊ฐ ์งง์์ง๊ณ ๊ฐ๋ ์ฑ์์ ํฐ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๋ค. ์ค์ํ ์ : ์ ์ญ๋ณ์๋ ํจ์์ ๋งค๊ฐ๋ณ์๋ก๋ ์ฌ์ฉํ์ง ๋ชปํจ
auto a = 100;
auto b = 100l;
auto c; // ERROR
vector<int> v;
auto be = v.begin(); // ์ด์ฒ๋ผ iteratorํ์ ๋์ ํ ์ ์๋ค
๋ฐ๋ณต๋ฌธ์์ STL์ iterator๋ฅผ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค. auto ํค์๋์ ํจ๊ป ์ฌ์ฉํ๋ค๋ฉด ๋ฐ๋ณต๋ฌธ์ด ์ผ๋ง๋ ๊ฐ๊ฒฐํด์ง๋์ง ์ดํด๋ณด์.
for(vector<int>::iterator i = v.begin(); i != v.end(); ++i){
// sth;
}
for(auto i = v.begin(); i != v.end(); ++i){
// sth;
}
for(auto& i : v){
// sth;
}
์์ ์ธ for๋ฌธ์ ๋์์ ๊ฐ๊ณ , ์ฝ๋์ ๊ธธ์ด๊ฐ ํ์ฐํ๊ฒ ์ค์ด๋๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค. ๋ง์ง๋ง ๋ฐ๋ณต๋ฌธ์ v๋ ๋ฐฐ์ด์ด๋ vector๊ฐ ๋ ์ ์๊ณ ์ฐธ์กฐ๋ณ์๋ก ์ฌ์ฉํจ์ผ๋ก์ ๋ณต์ฌ๊ฐ ๋ฐ์ํ์ง ์์ ๋ฉ๋ชจ๋ฆฌ์ ์ธก๋ฉด์์ ์ฑ๋ฅ์ด ์ข๋ค๊ณ ํ ์ ์๋ค.
ํํ ๋ฐํ ํ์์ด๋ ํจ์์ ๋ฐํ ํ์์ ๊ธฐ์กด์ ๋ฆฌํดํ์ ์ ์์น๊ฐ ์๋๋ผ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก ๋ค์์ '->'์ ์ฌ์ฉํ๋ฉฐ ๋ฐํ๊ฐ์ auto๋ก ์ง์ ํ ๊ฒฝ์ฐ์๋ C++11์์๋ ํํ ๋ฐํ ํ์์ด ํ์์์ง๋ง, C++14๋ถํฐ๋ ๋ฐํ ํ์ ์ ์ถ๋ก ํด ์ค๋ค. ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ์๋ํ ๋ฐ์ ๋ค๋ฅด๊ฒ ๋ฐํ ํ์์ด ๊ฒฐ์ ๋ ์ ์๋ ๋ฌธ์ ๋ฅผ ์ ๊ฒฝ์จ์ผ ํ๋ค.
auto function(int a, int b) -> decltype(a+b){
return a+b;
}
์ผ๋ฐ ํฌ์ธํฐ์ฒ๋ผ ์๊ฒผ์ง๋ง ์ค๋งํธ ํฌ์ธํฐ๋ ๋ฌด์์ผ๊น? ์ผ๋ฐ ํฌ์ธํฐ๋ณด๋ค ๋๋ํ๋ค๋ ๊ฒ์ ํ๋ก๊ทธ๋จ์์ ๊ฐ์ฅ ๋น๋ฒํ ๋ฐ์ํ๋ ๋ฒ๊ทธ์ ๊ด๋ จ๋์ด ์๋ค. ๋ฒ๊ทธ๋ฅผ ์ค์ผ ์ ์๋ค๋ ์ ์์ Smartํ ๊ฒ์ด๋ค. ๊ธฐ์กด C++์์๋ ๋์ ์ผ๋ก ํ ๋น๋ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐ๋์ delete๋ฅผ ์ด์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ํด์ ๊ฐ ํ์์์ ๋ฐ๋ผ Modern C++์์๋ Memory Leak, Segmentation fault๋ก๋ถํฐ ์์ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํ์ฌ Modern C++์์๋ ์ค๋งํธ ํฌ์ธํฐ๋ฅผ ์ ๊ณตํ๋ค.
๊ฐ์ฅ ๋ณดํธ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์์๋ก๋ auto_ptr์ด ์ค๋งํธ ํฌ์ธํฐ์ ์์๋ก ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋์์ง๋ง ์๋ฉธ๋์ ๋ฐฉ์์์ ๊ฐ์ฒด์ ๋ํ delete๋ฅผ ์ํํ๊ธฐ๋ณด๋ค๋ ๊ฐ์ฒด์ ํด์ ๋ง ์ํํ๋ ์น๋ช ์ ์ธ ๋จ์ ์ ๊ฐ์ง๊ณ ์์ด C++17๋ถํฐ ์ ๊ฑฐ ๋์๋ค. ์ด ๋ฌธ์ ์ ์ ์ํด unique_ptr์ shared_ptr์ ์ฃผ๋ก ์ฌ์ฉํ๊ฒ ๋์๋ค.
// ๊ธฐ์กด C/C++ pointer
Widget *getWidget();
void work()
{
Widget *wptr = getWidget();
// ์ฌ๊ธฐ์ Exception ๋ฐ์ ํน์ Returnํ๊ฒ ๋ ๊ฒฝ์ฐ, *wptr ๋ฉ๋ชจ๋ฆฌ ํด์ ๋ ์ด์ฉ์ฃ ?
delete wptr; // ์ง์ ๋ช
์์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํด์ผ ํจ.
}
// ๋ชจ๋ C++์ unique_ptr(์ค๋งํธ ํฌ์ธํฐ์ ์ผ์ข
)
unique_ptr<Widget> getWidget();
void work()
{
unique_ptr<Widget> upw = getWidget();
// Exception์ด ๋ฐ์ํ๊ฑฐ๋ ์ค๊ฐ์ Return ํ๋๋ผ๋ ๋ณ๋๋ก ์ ๊ฒฝ ์ธ ํ์๊ฐ ์์ต๋๋ค!
} // ๋ฉ๋ชจ๋ฆฌ๋ ์์์ ์๋์ผ๋ก ํด์ ๋ฉ๋๋ค.
์ฝ๋ ref) https://www.hanbit.co.kr/media/channel/view.html?cms_code=CMS8140000918
๋๋คํํ์(lambda expression)์ ์ด๋ฆ ์๋ ํจ์๋ก๋ ๋ถ๋ฆฌ๋๋ฐ python, C#, js๋ฑ์์ ์ด๋ฏธ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉ๋์๋ ๊ธฐ๋ฅ๋ค์ด๋ค. ์ ์ผ ํฐ ์ฅ์ ์ผ๋ก๋ ํจ์์ ์ธ๋ผ์ธํ๊ฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์๋ค.
๋๋คํํ์์ด๋ ์ด๋ค๊ฒ์ธ์ง ์ฝ๋๋ฅผ ๋ณด๊ณ ์ดํดํด๋ณด์. (in Effective Modern C++ Book)
std::find_if(container.begin(), container.end(),
[](int val) { return 0 < val && val < 10; });
[captures](parameters) -> return type { body }
/*
* captures: comma(,)๋ก ๊ตฌ๋ถ๋ ์บก์ฒ๋ค์ด ๋ค์ด๊ฐ๋๋ค. ์บก์ณ ๋ถ๊ฐ ์ค๋ช
์ ์๋์ ์์ฑํ์ต๋๋ค.
* [] : ์๋ฌด ์ธ๋ถ๋ณ์๋ ์ฌ์ฉํ์ง ์์
* [=] : ๋ชจ๋ ์ธ๋ถ๋ณ์์ ๊ฐ์ ์ ๋ฌ๋ฐ์์ ์บก์ณํ๋ค. value ๋ง ์ฌ์ฉํ๊ณ , ์ธ๋ถ๋ณ์์ ๊ฐ์ ๋ฐ๊พธ์ง๋ ๋ชปํจ.
* [&] : ๋ชจ๋ ์ธ๋ถ๋ณ์๋ฅผ ์ฐธ์กฐ๋ก ์ ๋ฌ๋ฐ์์ ์บก์ณํ๋ค. value๋ ์ฌ์ฉํ๊ณ , ์ธ๋ถ๋ณ์์ ๊ฐ๋ ๋ฐ๊ฟ ์ ์๋ค.
* [A] : ์ธ๋ถ๋ณ์ A๋ฅผ ๊ฐ์ผ๋ก ์ ๋ฌ๋ฐ์์ ์บก์ณํ๋ค. ๋จ A์ value๋ ์ฌ์ฉํ ์ ์์ผ๋ ๊ฐ์ ๋ฐ๊ฟ ์ ์๋ค.
* [&A] : ์ธ๋ถ๋ณ์ A๋ฅผ ์ฐธ์กฐ๋ก ์ ๋ฌ๋ฐ์์ ์บก์ณํ๋ค. value๋ ์ฌ์ฉํ๊ณ , ๊ฐ๋ ๋ฐ๊ฟ ์ ์๋ค.
* parameters: ํจ์์ ์ธ์๋ค์ด ๋ค์ด๊ฐ๋๋ค.
* return type: ํจ์์ ๋ฐํํ์
๋๋ค.
* body: ํจ์์ ๋ชธํต์
๋๋ค.
*/
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
int main(){
auto a = 5;
[&](){a = 3;cout<<a<<endl;}();
}
ํจ์ ํฌ์ธํฐ๋ก ์ฌ์ฉํ๊ธฐ 1
int main(){
auto a = 5;
auto func = [&](){a = 3;cout<<a<<endl;};
func();
}
ํจ์ ํฌ์ธํฐ๋ก ์ฌ์ฉํ๊ธฐ 2
int main(){
auto a = 5;
function<void()> func = [&](){a = 3;cout<<a<<endl;};
func();
}
๋๋ค๋ฅผ ๋ฐํํ๋ ํจ์
auto a = 5;
auto getLambda() {//C++14
return [&]() {a = 3;cout<<a<<endl;};
}
int main(){
auto func = getLambda();
func();
}
์ฌ๊ทํจ์๋ก ์ฐ์ด๋ ๋๋ค
int main(){
function<int (int)> func = [&func] (int num) -> int
{
if(num <= 1)return 1;
else return num*func(num-1);
};
auto a = func(5);
cout<<a<<endl;
}
์ด๋ ์๋งจํฑ์ด๋ C++11์์ ์ถ๊ฐ๋ ๋ฌธ๋ฒ์ผ๋ก Move Semantics์ด ๋ฑ์ฅํ ์ด์ ์ด๊ธฐ๋ ํ๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด C++ ๋ณต์ฌ๊ฐ ๊ฐ์ง C++ Copy Semantics์ ๋ฌธ์ ์ ์ ๋ํด์ ๋จผ์ ์๊ฐํด๋ณด์. C++์์๋ ์ด๋ ํ ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ณต์ฌํ๋ ์ผ์ด ๊ฐ๋ฅํ๋ค. ํ์ง๋ง ์ด ๊ตฌ๋ ๋ฐฉ์์
- ์ฌ์ง ๋ณต์ฌ๋ฅผ ์ํ์ฌ PC์ ํด๋๋ฅผ ํ๋ ๋ง๋ค๊ณ
- SD ์นด๋์์ ์ฌ์ง๋ค์ ์ ํํด ์ปดํจํฐ๋ก ๋ณต์ฌํ๊ณ
- ๋ณต์ฌ๊ฐ ๋๋๋ฉด ์๋ณธ ์ฌ์ง์ ์ญ์ ํ๊ณ
- ์ญ์ ๊ฐ ๋๋๋ฉด ์ด ๋ณต์ฌํ ์ฌ์ง๋ค์ ๊ฐ์ง๊ณ ์์ ์ ์์ํ๋ ๋ฐฉ์ ์์ฒ๋ผ ์ ๋ง ํจ์จ์ด ๋จ์ด์ก๋ค. ์ด๋ฌํ Copy ๋นํจ์จ์ ์์ ๊ธฐ ์ํ์ฌ Modern C++์์๋ Move Semantics์ด๋ผ๋ ๊ฐ๋ ์ ์ ์ฉ์์ผฐ๋ค. ๋ฉ๋ชจ๋ฆฌ ์์ ๊ถ ์ด์ ์ผ๋ก ๋น์ฉ์ด ๋ฐ์ํ์ง ์๋๋ค๋ ํฐ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๋ค.
Move Semantic์ ์ฌ์ฉ ์์๋ฅผ ์์๋ณด๊ธฐ ์ ์ L-value์ R-value์ ๋ํด ์์๋ณด์.
L value๋ ์ ๊ทผํ ์ ์๋ ์ฃผ์๋ฅผ ๊ฐ์ง ๋ณ์๋ฅผ ๋งํ๋ค.
- ์ด๋ฆ์ด ์๋ ๋ณ์, ํจ์ ex) int a; foo();
- ์ ํ ์ฆ๊ฐ ์ฐ์ฐ์ ex) ++a;, --b;
- L-value ๋ฐฐ์ด์ ์ธ๋ฑ์ค ์ ๊ทผ ex) a[n];
prvalue๋ผ๊ณ ํ๋๋ฐ ์ ๊ทผ์ ํ ์ ์์ง๋ง ์ฃผ์๋ฅผ ๊ฐ์ง์ง ๋ชปํ ํํ์์ ๋งํ๋ค.
- ๋ฆฌํฐ๋ด ๊ฐ (string์ ์ ์ธ)
- ํํ ์ฆ๊ฐ ์ฐ์ฐ์ ex) a++, b--
- ๊ฐ ๋ฆฌํด ํจ์ ํธ์ถ ex) return str1+str2;
xvalue๋ ์ ๊ทผํ ์ ์๋ ์ฃผ์๋ฅผ ๊ฐ์ง์ง๋ง ์ด๋ ์ฐ์ฐ์ ํ ์ ์๋๊ฒ์ ๋งํ๋ค.
- rvalue ์ฐธ์กฐ๋ฅผ ๋ฆฌํดํ๋ ํจ์ ex) std::move(x)
- rvalue ๋ฐฐ์ด์ ์ธ๋ฑ์ค ์ ๊ทผ ex) r[n]
Pure rvalue์ X-value๋ฅผ ๋ฌถ์ด์ R-value๋ผ๊ณ ๋งํ๋ค.
int tmain(int argc, _TCHAR* argv[])
{
int num1 = 5, num2 = 3;
num1 = 10; // num1์ lvalue, 10์ intํ prvalue
num1 = num2; // num1์ lvalue, num2์ lvalue
int num3 = num1 + num2; // num3์ lvalue, num1 + num2์ prvalue
std::move(num3); // rvalue ์ฐธ์กฐ๋ฅผ ๋ฆฌํด xvalue
static_cast<DWORD>(num1) // ๊ฐ์ผ๋ก ์บ์คํ
lvalue
static_cast<DWORD&&>(num1) // rvalue ์ฐธ์กฐ๋ก ์บ์คํ
xvalue
}
str1์ str2๋ฅผ swapํด์ผ ํ๋ ๊ณผ์ ์ ๊ฑฐ์น ๋ ์ฐ๋ฆฌ๋ ์์ ๋ณ์(string tmp)๋ฅผ ๋ง๋ค์ด ์์ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์ ๊ต์ฒดํ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์๋ค. ํ์ง๋ง ์ด ๊ณผ์ ์์ ๋ณต์ฌ๊ฐ ์ธ๋ฒ ์ผ์ด๋๊ฒ ๋๋ค. ์ฐ๋ฆฌ๋ ๊ตณ์ด ๋ฌธ์์ด ๋ด์ฉ์ ๋ณต์ฌํ ํ์ ์์ด string_content์ ์ฃผ์๊ฐ๋ง ์๋ก ๋ฐ๊ฟ์ฃผ๋ฉด ๋๋๊ฒ์ ์๊ณ ์๋ค. ์ข์ธก๊ฐ์ด ์ฐ์ธก๊ฐ์ผ๋ก ์ทจ๊ธ๋ ์ ์๊ฒ ๋ฐ๊ฟ์ฃผ๋ ํจ์๊ฐ ์์๊น? std::move๋ฅผ ์ฌ์ฉํ์!
Move Semantics
#include <cstring>
#include <algorithm>
class string
{
char* data;
public:
string(const char* p)
{
size_t size = std::strlen(p) + 1;
data = new char[size];
std::memcpy(data, p, size);
}
Move Semantics์ ๋ํ ์์ธํ ์ ๋ณด๋ microsoft ๊ณต์ ๋ฌธ์, stackoverflow์ ์ฐธ์กฐํ๋ฉด ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ค.
Modern C++์์๋ C/C++์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ด์๋ ๋ฐฐ์ด์ STL๋ก ์ง์ํด์ค๋ค. ๊ธฐ์กด STL์ ์ฌ์ฉํ ๋ ์ฐ๋ฆฌ๋ Vector์ ๋ง์ด ์ฌ์ฉํด์๊ณ ์ฌ์ค Vector๋ ์์ฑ๊ณผ ์๋ฉธ์ ๋๋ ๋น์ฉ์ด ๊ฝค ํฌ๊ณ , ํ ๋ฒกํฐ์ ๊ฐ์ฒด๋ 4byte๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋นํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
C++11๋ถํฐ ์ถ๊ฐ๋ ํค์๋๋ก ๋ํฌ์ธํฐ๋ฅผ ๋ปํ๋ค. nullptr์ ํฌ์ธํฐ๋ง์ ์ํ NULL์์์ด๋ค. Modern C++์ด์ ๊น์ง๋ ๋ํฌ์ธํฐ๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์์ '0'์ ์ฌ์ฉํ๋๋ฐ ํจ์ ์ธ์๋ก ๋๊ธฐ๊ฒ ๋์์ ๋ ์ ์ํ์ผ๋ก ์ถ๋ก ๋๋ ๊ฒฝ์ฐ๊ฐ ์์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๊ณ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ์ฌ nullptr์ด ๋ฑ์ฅํ๋ค.
๊ธฐ์กด C/C++์์๋ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ ๋ Window๋ Win32 API, ๋ฆฌ๋ ์ค๋ pthread๋ฅผ ์ฌ์ฉํ์ฌ์ผ๋ง ํ๋ค. Modern C++์์๋ ์ค๋ ๋์ ๊ดํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ค์ผ๋ก ํฌํจ๋์ด ์ค๋ ๋๋ฅผ ๋ค๋ฃจ๊ธฐ์ ๋งค์ฐ ํธ๋ฆฌํด์ก๋ค.
์ ๊ท์์ Modern C++์์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋์๋ค. std::regex ๋ฑ์ ์ฌ์ฉํ์ฌ ์ ๊ท์์ ์ฌ์ฉํ ์ ์๋ค.