posted by REDFORCE 2017. 3. 22. 18:19

목차


1. Auto

2. range based for

3. enum class

4. non-static data member initializers

5. initializer lists

6. default / delete definition

7. override / final

8. emplacement

9. constexpr

10. lambda

11. random

12. thread


이번 글에서는 [4-5편] non-static data member initializers 와 initializer lists


를 함께 다루도록 하겠습니다.


4, 5편 내용은 짧기 때문에 두 편을 한 글로 붙였습니다.



4. Non-static data member initializers


 - C#, Java 처럼 멤버 변수 정의와 동시에 초기 값을 할당 할 수 있다.


대체 이것이 무슨 말?? 이냐 하면


역시나 코드로 바로 보도록 하자.


Class TEST
{
public:
void print()
{
std::cout << n1 << ", " << s1 << std::endl;
}
private:
int n1 = 100;
std::string s1 = "test";
};
view raw initializer.cpp hosted with ❤ by GitHub



위에서 private: 아래의 멤버 변수를 살펴보면


선언과 동시에 초기화가 진행 되는 것을 볼 수 있다.



옛날엔 이거 안됐다!!


근데 지금은 된다 ㅡ, .  ㅡ;


학창 시절 Java를 배웠을 때는 당연히 되던거라 게임 프로그래밍으로 넘어오면서 C++을 할 때 이게 안됐던 시기엔


어 = _=..왜안되지...원래안되나...하고 넘어갔었으나


C++11로 넘어오면서 가능해진 것으로 알고 있다.


즉 헤더에서도 멤버 변수 선언과 동시에 초기화가 가능하다!



여기까지는 다들 "뭐...음..그래...그래서...? 당연하거 아닌가?" 하고 넘어 갈 수 있다.



다시 먼저 코드를 보도록 하자.


class TEST
{
public:
void print()
{
std::cout << n1 << ", " << s1 << std::endl;
}
//private:
int n1;
std::string s1;
};
TEST test { 1, "test" };
test.print();
view raw initializer.cpp hosted with ❤ by GitHub


살펴보면 private이 주석 처리 되어


멤버변수들이 접근한정자 public: 으로 바뀌게 되었고



외부에서 TEST test { 1 , "test" }; 로 초기화가 가능해졌다!


이 말인즉 public 접근이 가능한 클래스 멤버 변수가 외부에서 초기화가 바로 가능하다 라는 점이다.


이걸 잘 응용해본다면 외부 다른 클래스에서도 해당 클래스의 new로 선언함과 초기화를 바로 진행이 가능하게 만들 수 있다는 것!



그 외에도 기본적인 타입들에 대해서 initializer를 쓸 수 있다.


std::string str1 { "hello world" };
std::string str2 = { "hello world" };
std::string str3 { };
std::string str4 = { };
std::pair<int, int> p1 { 10, 20 };
std::pair<int, int> p2 = { 10, 20 };
view raw initializer.cpp hosted with ❤ by GitHub


5. initializer lists

  • 초기화 리스트 전용 type
  • 함수의 인자, 유저 정의형, STL 컨테이너의 초기화에 사용할 수 있다.

위에서 본 initializer와 마찬가지로 STL컨테이너도 똑같이 적용시킬 수 있다.

Template을 이용한 Vector 컨테이너 초기화



template <class T>
class vector{
public:
vector(std::initializer_list<T>);
};
std::vector<int> v { 1, 2, 3 };
view raw initializer.cpp hosted with ❤ by GitHub

일반적인 배열 초기화


int sum ( initializer_list<int> li )
{
return accumulate(li.begin(), li.end(), 0);
}
auto result = sum ({ 9, 8, 7, 6 )};
view raw initializer.cpp hosted with ❤ by GitHub

(오오...auto 슨상님이 등장했다)



결론. 멤버 이니셜라이즈를 통해 초기화 구문을 쉽게 정의 할 수 있다!

posted by REDFORCE 2017. 3. 22. 17:55

목차


1. Auto

2. range based for

3. enum class

4. non-static data member initializers

5. initializer lists

6. default / delete definition

7. override / final

8. emplacement

9. constexpr

10. lambda

11. random

12. thread


이번 글에서는 [3편] enum Class 에 대해서 적어보도록 하겠습니다.


enum Class에 앞서 먼저 enum이 뭔지 알아야하니 같이 나열해보며 비교하도록 하겠습니다.


3. enum class


enum 

  • c++11의 enum은 C++03 표준과 다르게 두 종류의 enum으로 바뀌었다.
  • 강한 형 사용과 범위를 가진다.
  • 'unscoped enumeration'과 'scoped enumeration'
  • unscoped enumeration은 기존(C++03) enum과 비슷

 

//unscoped enumeration
enum ITEMTYPE : short
{
WEAPON,
EQUIPMENT,
GEM = 10,
DEFENCE,
};
short ItemType1 = WEAPON;
short ItemType2 = ITEMTYPE::WEAPON;
view raw enumclass.cpp hosted with ❤ by GitHub


위 코드를 보면 스콮이 있는 enum과 없는 enum으로 구분되어 있습니다.


scoped enumeration은 ITEMTYPE:: 이라는 네임스페이스가 따라 붙는 것을 볼 수 있습니다.

(아...영타 치기 뭔가 귀찮네요...= _=)


기존의 enum은 위에 적혀있는 ITEMTYPE:: 스페이스가 없는 enum입니다.



이게 왜 좋은거냐?


라고 이제 생각할 때가 됐는데요.



우리가 보통 enum을 헤더에 선언하여 사용하다보면 대체 이 enumeration값들이 어디에 있는 거여? 하고 햇갈리게 됩니다.


따라서 scoped enumeration 같은 경우 네임스페이스가 따라 붙기 때문에


아 거기서 썼던 enum이구만~ 하고 바로 알 수 있습니다.


//scoped enumeration
enum class CHARACTER_CLASS : short
{
WARRIOR = 1,
MONK,
FIGHTER,
};
CHARACTER_CLASS CharClass = CHARACTER_CLASS::WARRIOR; // Work~!
short CharClassType = FIGHTER // error !!!
view raw enumclass.cpp hosted with ❤ by GitHub



그리고 위와 같이 enum class로 선언하면 네임스페이스를 붙이지 않을 경우 error를 띄우게 됩니다.


강제적으로 강한 형 사용을 강요하게 되조.


덕분에 enumeration 값이 어디에 있던 것인지 강제적으로 명시하는 코드를 작성하게 됩니다.


어떻게 보면 귀찮다~ 라고 볼 수도 있지만


향후 다시 이 코드를 봤을 때 도움이 많이 되고 유지보수에도 많은 기여를 할 거라 예상 됩니다.



그래서~ 필요하다면 쓸 수 있게 끔 타입 케스팅 자체도 지원을 하고 있습니다.


// unscoped enumeration
int i = WEAPON;
// scoped enumeration
int i = static_cast<int>( CHARACTER_CLASS::WARRIOR);
view raw enumclass.cpp hosted with ❤ by GitHub



enum class 자체에 대해서는 그닥 알게 없을 수도 있으나 이런식으로 C++ enum을 쓸 수 있다를 알고 가시면 좋을 것 같습니다.


(enum Class를 활용한 뒤부터는 모든 enum을 죄다 이걸로 싸그리 바꿔버리고 있는...)



다음 글 non-static data member initializers 에서 뵐게요!

posted by REDFORCE 2017. 3. 22. 17:20

이번 글에서는 1편의 auto에 이어서


range based for에 대해서 적어보겠습니다.


목차


1. Auto

2. range based for

3. enum class

4. non-static data member initializers

5. initializer lists

6. default / delete definition

7. override / final

8. emplacement

9. constexpr

10. lambda

11. random

12. thread


2. range based for


 A. range based for?? 


번역하자면 범위 기반 For 라고 적고 단순히 이해하자면 반복문을 쉽고 안전하게 쓰기 위한 For~ 라고 보면된다.



간단한 설명

  • C++11 기능 중 'auto'와 더불어 간단하면서 유용한 기능
  • VC의 'for each'와 유사
  • 반복문을 아주 쉽고 안전하게 사용할 수 있다.
  • C++ STL의 컨테이너, 배열 등에 사용할 수 있다.


코드를 먼저 살펴보면 한눈에 이해할 수 있다.


int NumberList[5] = { 1, 2, 3, 4, 5 };
// Basic For
for( int i = 0; i < 5; i++ )
{
std::cout << i << std::endl;
}
// For each from VC
for each( int i in NumberList )
{
std::cout << i << std::endl;
}
// Range Based For
for( auto i : NumberList )
{
std::cout << i << std::endl;
}
view raw rangefor.cpp hosted with ❤ by GitHub



가장 첫번째 부터 


 (1) For (일반적인)

 (2) For each

 (3) range based for  로 되어있다.


여기서 눈여겨 볼 것은 auto를 활용한 range based for 문이다.


(3)에서 결국 auto i  값이 입력받은 배열의 iterator로써 활용이 된다.


편하게 auto i 의 값이 입력받은 배열의 begin 부터 end 까지 반복 수행하게 된다.



마찬가지로 std::vector 와 같은 컨테이너에서도 활용이 가능하다.


//==============================
std::vector<int> NumberList;
for( auto i : NumberList )
{
std::cout << i << std::endl;
}
//==============================
std::unordered_map<int, std::string> NumString;
for( auto : NumString )
{
std::cout << "Key : " << i.first << ", value : " << i.second << std::endl;
}
view raw rangefor.cpp hosted with ❤ by GitHub



일반적인 배열을 입력해줬던 내용대로 똑같이 컨테이너를 넣어주면 된다.




그리고 이 글에서 가장 핵심적인 부분!


1. for문에서 의도치 않은 값 복사를 피하고 싶다면?


2. 그리고 이런 range based for문을 활용하면서 값 변경을 막고 싶다면?


3. 둘 다 하고싶다면?


아래와 같이 코드를 수행하면 된다.


//avoid Copy!
for( auto &i : NumberList )
//avoid Value Change!
for( auto const i : NumberList )
//avoid Copy & Value Change!
for( auto const &i : NumberList )
view raw rangefor.cpp hosted with ❤ by GitHub



값 복사를 피하고 싶다면 레퍼런스를 받아오도록 하게 하면되고


값 변경을 방지하고 싶다면 const를 이용하여 막을 수 있다.


둘다 하고싶다면 위 내용 둘 다 수행하면 된다.




range based for문은 확실히 반복문을 수행하는데 편리하고 쉬운 방법이면서도 안전하게 사용을 할 수 있는 방안이다!


결론. auto 짱짱맨! |O_ o/ x 256




ps. 내가 자꾸 auto 성애자가 되는 것 같다..하앜..