달력

08

« 2018/08 »

  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  




이번 항목부터 리소스 누수, 예외처리에 대한 이야기가 펼쳐진다.
와~ 신난다.

본론으로 바로 들어가자.

1. 데이터를 받아서, 기록하려 한다.

2. 데이터를 파일에 저장되어 있다.

3. 파일안에는

"개"
"고양이"
"코끼리"
...

여러 동물들에 대한 이름과 정보가 들어가 있다.

다음과 같은 상황에서 DB를 구축한다고 하였을 때,

AAA라는 추상 클래스를 생성 -> ex) "동물"

AAA를 상속받은 BBB 클래스 -> ex) "개"
AAA를 상속받은 CCC 클래스 -> ex) "코끼리"
AAA를 상속받은 DDD 클래스 -> ex) "고양이"

라고 한다면,

다음 클래스가 대충 이해가 갈 것이다.


복잡하려나--; 가능한 쉽게 한다고 하는데..
뭐, 정 복잡하면.

이 부분만 봐도 된다.

readAAA 안에서는 새로운 객체를 생성하여
return AAA* 를 하게 되는데,
만약.

이 부분에 예외가 발생하면 어떻게 될까?
delete 부분은 수행되지 않을 것이고.
메모리 누수가 발생할 것이다.

그래서 예지력이 뛰어난 우리는 누수를 막기 위해,
다음과 같은 예외처리를 삽입하였다.

아 정말 뛰어난 예외처리다. 이제 문제가 발생해도,
메모리 누수가 일어 나지 않을꺼야.
라고 좋아 하고 있는데,
뭔가 이상하다.
만약 pa의 이름이 바뀌어서.
pa2가 되었다면.
catch안에 있는 pa도...
밖에 있는 pa도, ps2로 바꿔주는 귀찮음이 생길 수 있고.
delete pa 를 2번 쓴다는것 자체가 뭔가 무의미 하고 복잡하게 느껴진다.

라고 생각이 든다고 한다.(진짜?)
즉, 수정하고 나니 뭔가 잘못된 것 아니야? 라고 느낀다는 것이다.

쉽게 말해, 예외가 발생하든, 발생하지 않든.
pa는 삭제 되어야 한다는 것이고
구지 2번 쓸 필요 없이 다른 방법을 찾아 보자. 라는것이다.

먼저 그 해결책에 대해서 2가지 방법을 제시 하고 있는데,

그 첫번째. 스마트 포인터.

자세한 내용은 후에 항목에서 소개가 될테니 넘어가고.

쉽게 이야기 하면,
자신의 유효범위를 벗어나면 자신이 가리키고 있는 메모리를 삭제 할 수 있는 "포인터처럼 동작하는 객체"라고 한다.

일단 c++ 라이브러리에는 auto_ptr 이라는 "그런 일"을 하는 객체가 이미 정의되어 있다고 한다.
대충 개념만 따지면 다음처럼 말이다.

"보고 있나 플머?"
뭐 여튼, 포인터 같이 활동하는 객체 라는것을 주의하면서
생성자, 소멸자를 통해 메모리 누수를 막고 있다는 것을 파악하면 된다.

책에서는 "사실, 단순 데이터를 보관하는거면 그냥 stl의 vector를 쓰세요."
라고도 말 하고 있지만....;;
일단! 다음과 같이 auto_ptr이라는 객체를 통해
기존의 코드는 이처럼 바뀌게 될 것이다.

자, 이렇게 함으로써,
pa->process();
에서 예외가 발생하더라도, 메모리 누수는 발생하지 않을 것이다.
"보고 있나 플머?"ㅋ

또한, 이와 같은 형식으로 해결 하는 또 하나의 누수 막기 스킬이 존재 한다고 하는데,
이는 window handle 에서도 사용할 수 있다고 한다.
코드를 보자.

이 코드의 문법상이나 올바름을 보지 말고.
흐름을 보도록하자.
핸들을 통해 window를 생성하고.
작업을 진행하고.
해제하는 일을 하는 함수인 displayInfo는.
예외가 발생하면 리소스 누수를 일으킬 수 있는 여건을 가지고 있다.

이와 같은 부분에 대해서 해결책은 auto_ptr과 매우 흡사하다.
바로 코드를 보도록 하자.

마찬가지로 흐름을 보자.
문법은 조금 옳바르지 않을 수 있다.
여튼, 다음처럼 windowhandle을 받는 클래스를 생성하였고.
이제 displayInfo는 메모리 누수를 일으키지 않을 것이다.

auto_ptr과 마찬가지로 추가적인 delete 작업,
즉, destroyWindow는 하지 않아도 된다.

이 처럼, 이번 항목에서 의미 하는 것은,
예외가 발생하였을 때 생기는 메모리 누수를 막기 위해선,
해당 객체를 그냥 포인터로 선언하지 말고,
생성과, 해제를 포괄적으로 담당하는 객체를 생성하라는 것이다.

하지만 이런 부분에 대해서도 문제는 존재 하는데,
바로, 소멸자에서 리소스를 자동으로 해제하다가 생기는 예외처리.

이 부분에 대해선 항목 10, 11에 대해서 다시 언급한다고 하니.
일단 이번장에서 배운것 부터 재대로 기억하고 있자.
Posted by 안식의후크




c++에서 흔히 사용하는 new, 그리고 delete.

그안에 감춰진 비밀을 파해쳐 보자! 팍팍!!(...)


다음은 흔히들 사용하는 new와 delete의 사용 예중 하나이다.
먼저 new 부터 확인해 보자.
new, 보통 포인터에 메모리를 할당하는 상황에서 사용되는데,
이 연산자는 두단계를 거쳐서 일을 수행한다.
먼저, 요청한 타입의 객체를 담을 수 있는 크기의 메모리를 할당.
그 다음 생성자를 호출하여 객체 초기화를 수행하는 것이다.

이 두단계는 바꿀 수가 없다. 당연한 이치다.
여기 까지 보면, "이게 뭐?" 그래서 어쩌란건데..? 라는 의문이 들지도 모르겠지만. 중요한건 지금부터.

new가 하는 첫번째 일
타입의 객체를 담을 수 있는 메모리 할당.
이를 operator new 라고 하며,
우리는 그 operator new를 재정의 할 수 있다고 한다.
new 연산자 자체를 오버로딩하는 것은 "불가능" 하지만.
메모리를 할당하는 operator new에 대해서는 원하는 방식으로 수정할 수 있다는 것이다.
(근데 별로 하고 싶진 않네...)

일단 이번 항목 자체는 operator new를 오버로딩 하는 방법이 아니다.
조금더 보자. operator new 함수는 다음과 같이 선언된다.

이 함수는 void* 타입으로 반환을 하게 되는데,
초기화 되지 않은 원시 메모리의 포인터를 반환하기 때문이다.
operator new 를 오버로딩 할 때 추가적인 매개변수를 넣게 할 수도 있다는데,
이 때에 주의점은 첫번째 매개변수는 무조건 size_t size를 해야 한다는 것이다.
new를 사용하지 않고, 단순히 메모리 할당만 하고 싶다.
이럴 경우에는 그냥 편하게.

이처럼 해주면 된다. 이렇게 하면,
string 타입의 객체를 담을 수 있는 메모리 덩어리를 할당해서 그 메모리 포인터를 반환해 준다고 한다.

좀 쉽게 설명하면 operator new 는 c의 malloc과 마찬가지로 메모리만 할당하는 것뿐이라고 한다.
즉, 다음과 같이 new 연산자를 호출 하면,

이 부분에서 memory에 값을 세팅, 객체를 초기화 하는 부분은.
우리가 어찌 할 수 없는 부분이라고 하니,
뭘 어떻게 조작해 볼 생각따윈 집어 치우고, 저런 방식으로 new가 진행되는구나~
하고 넘어가는 것이 좋을 듯 하다.
즉, 힙에 할당하는 용도에 우리가 쓸 수 있는 수단은 new 연산자 뿐이라는 거다.

음. 뭔가 설명이 부족한거 같은데, 어찌 보면
결국 new로 할당하라는거잖아? 라고 볼 수 있겠지만,
꼭 그렇진 않다. 지금까지의 이야기는 쉽게 말해 new하여 메모리를 할당하였을 때,
호출 되는 순서, 라고 볼 수도 있다. 그 첫번째에 operator new가 있다는 것,
그리고 operator new는 malloc 처럼 메모리를 "할당"하는 일을 맡고 있다는 것.
일단 그것을 파악하고 넘어가는 것이 가장 중요하다고 생각한다.

이쯤에서 나오는 단어가. 메모리 지정 new(Placement new)라는 것인데,
나도 읽으면서 몇번을 해깔려서 자꾸 보게 되는데,
잘 설명할 수 있을지는...
자. 코드를 보자.

이게 공유 메모리나 메모리-맵 I/O를 사용하는 어플리케이션을 만들 때 꽤 유용하다는데...
객체를 특별한 주소 공간이나 별도의 루틴을 통해 할당한 메모리에다가 두어야 하기 때문이란다.
그러니까, 이미 할당되어 있는 메모리 공간, 아직 뭔가 들어가 있지 않은 빈 방에다가.
내가 원하는 것들을 그곳에다가 채워 넣고 싶을 때 이런식으로 사용한다곤 하는데.
아직 그런 경험이 없어서, 어떨때 어떤식으로 사용해야 하는진 잘 모르겠다.
가끔 이런 소리 나오면, 가슴속으로. "아.. 이게 뭔 개소리야." 라고 생각하는걸 보면.
난 진짜 슈퍼 개 잉여인가. 싶기도 한데.
여튼, 다시 본론으로 들어가서.
저런식으로 new를 호출하게 되면,

이처럼 operator new가 호출이 된다고 한다.
operator new가 메모리 할당이니까,
저런식으로 내가 원하는 공간을 메모리 할당 지역으로 쓰겠다.
라고 보면 될 것 같다.
메모리 지정 new를 사용 하려고 했을 경우.
를 지정해 주면 된다고 한다.
참 간단하다고 한다.
"뭐!? 임마?"

사실 좀 복잡하게 설명하긴 했지만, 개념만 따지면 뭐, 그렇게 어렵진 않은거 같긴한다. 정말로.
new 를 쓴다.
메모리를 할당한다.
객체를 생성하고 초기화 한다.

operator new를 쓴다.
메모리만 할당한다.
끝.

이처럼 new와 operator new는 분명 다르다.
구지 수식을 표현한다면,
new >(포함) operator new 가 될려나?

어째뜬 new를 사용하게 되면 operator new를 거치기 때문에.
operator new를 수정,
new를 사용하면 new를 사용 할 때, 내가 원하는 공간을 배치하는 것이 가능하다는 것이다.

operator new를 봤으니.
이제 delete를 보자.

지금까지 이해를 했다면,(내 설명이 후져서 이해를 했을진 모르겠다.)
delete가 어떻게 돌아가냐고 물었을 때,
얼추 예상은 할 수 있을 것이다.

new와 반대.

처럼 진행될 것이다.
만약 사용자가 operator new를 통해 메모리를 생성했다면,
operator delete 를 사용해 메모리를 해제하여야 할 것이다.

이처럼 말이다.

조금더 이야기 하자면,
메모리 지정 new를 사용해. 생성하였다면
delete로 지우면 안될 것이다.
delete 연산자는 operator delete 함수를 호출하여 메모리를 해제하게 되는데,
그 객체를 담고 있는 메모리는 operator new로 할당된 것이 아니라. 사용자가 직접 정한 어딘가에 할당하였기 때문이다.

나도 자꾸 해깔리는데, operator new와 메모리 지정 new는 다르다.
new를 사용하면 operator new를 거쳐가는 것이고.
메모리 지정 new는 기존의 operator new가 아닌 내가 원하는 어떤 공간에 넣은 것이기 때문에.
일반적인 delete를 사용하면 그게 어딘지 모른다는거다.

음. 다음 코드를 보면 대강 감이 올 것이라고 생각한다.


복잡하네.
이쯤에서 좀 정리가 필요 한거 같은데,

new를 사용하면,
operator new를 사용하여 메모리를 할당하고.
그 메모리에 생성자, 초기화 한다.
delete를 사용하면
그 메모리에 소멸자에 들른 후,
메모리를 삭제한다.

operator new만 사용하게 되면,
메모리를 할당만 할 수 있고.
operator delete를 통해 삭제만 할 수 있다.

메모리 지정 new를 사용하면,
이미 할당되어 있는 공간에 내가 원하는 녀석으로 생성, 초기화 할 수 있으며,
그렇게 하였을 경우에는,
꼭 그 녀석을 삭제하는 부분을 따로 만들어서 삭제,
delete로 마냥 삭제 해서는 안된다.

정도로 정리 할 수 있을 것 같다.
ps : 만약 내가 생각한 것이 틀리다면, 꼭 틀리다고 해주세요. 제발;;

자 어째뜬 마지막으로.
그렇다면 이녀석들이 단일이 아니라. 배열이라면??
그것은 그것대로 따로 조정을 해 주어야 한다고 한다.
즉,

이와 같은 경우는.
operator new가 아니라.
operator new [] 가 호출 된다고 한다.

마찬가지로 operator delete가 아
닌 operator delete [] 가 호출 되는건 당연지사.

operator delete[]의 경우엔 오버로딩 하기 위해선,
제한이 존재 한다는데, 책에서는 언급되어 있지 않다.

뭐, 대충 여기 까지 인데,
new와 delete는 어찌 손 볼 수 없다.
하지만 내부적으로 메모리 할당, 해제는 마음만 먹으면 어느정도 손 볼수 있다는게 책에서 내리는 결론.
"하는 일을 수행하는 방법"은 고칠 수 있을 지 몰라도.
"하는 일" 자체를 바꿀 수 없다는 것이다.



ps2 : 복잡하네 정말.
정말 이런걸 다 생각하면서 코딩하는 사람이 있기는 한거냐?? 젠장.
여튼 항목8은 좀 개념적으로 복잡하네
어찌 보면 쉬운거 같기도 한데,
처음 보면 뭔 소린가 싶기도 할거 같고.
벌써 새벽 5시 반이넘었네.
시티 헌터나 보고 자야지.징징
Posted by 안식의후크




시작은 단축 평가 처리에 대해서 언급되어 있다.

복합적인 불린 표현식을 평가 할 때.
모든 조건을 다 보는것이 아니라. 특정 조건으로 인해 최종 결과 값이, 참 또는 거짓 이라고 판명이 났을 때.
남은 조건들을 검사하지 않고 넘어 가는 것을 말하는데.


여기 까지는 이미 알고 있거나, "아 그렇군!" 하고 넘어 가면 그만인데
이제 &&, || 연산자를 오버로딩 한다고 생각하자.

다음과 같은 문제가 발생한다.

다음 처럼 보여진다는 것이다.
잘 이해가 가지 않을 수도 있지만.
쉽게 생각하면 문제는 다음과 같다.
첫째, 모두 검사를 해야 하기 때문에 단축 평가가 이루어 지지 않는다.
둘째, ex1이 먼저 평가 될지, ex2가 먼저 평가 될지 모른다는것이다.
단축 평가는 c, c++에서 정해져 있는 기본 기능이다.
만약 &&, || 연산자를 오버로딩 하지 않았다는 전재로.
단축 평가를 생각하면서 조건식을 넣었던 A씨는
B씨의 오버로딩으로 문제가 발생할 여지가 존재한다는 것이다.
물론 그런 부분을 처음에 약속하여 방지 하는 것은 가능할지도 모르겠으나.
그것이 옳지 않은 방법이라는 것은 구지 말하지 않아도 충분히 알 것이라고 생각한다.

다음은 ,(쉼표) 연산자 인데.
사실 흔히 사용하는 연산자는 아니다.
사용하는 좋은 예를 코드로 보여주고 있는데.
내용은 다음과 같다.

문자열을 반전시키는 함수인데,
마지막 부분을 보면 ++i, --j 를 볼 수 있다.
, 연산자의 경우 순서를 따지면
먼저 i를 증가 시키고,
그 다음 j를 증가 시킨다.
그 순서에 의문이 생긴다면,
처럼 해보자.
값은 --j가 나올 것이다.
여튼, 이것 또한 문제만 콕 찝어서 넘어 가자면,
오버로딩 하였을 때, 그 안에서 --j를 먼저 실행할지, ++i를 먼저 실행할지
순서를 보장 할 수 없다는것!!
그렇기 때문에 , 연산자 또한 오버로딩을 하지 말아라! 라는것이 이번 항목의 결론인것 같다.

한가지 의문은 오버로딩을 할 순있지만, 해서 좋지 않을 것이라면,
애초에 하지 못하게 하는것이 더 낫지 않았을까? 하는 생각도 들긴 한다만...

뭐... 높으신 분들께서 생각이 있으셨겠죠;;하하 미천한 저 따위가 뭘 알겠나요.

이번 항목은 생각보다 별거 없었다.
앞으로 남은 모든 항목이 이런 수준의 난이도라면 참 좋겠어.제길.
Posted by 안식의후크



흔히 쓰는, ++, -- 연산자에 대해서 설명하고 있는 항목이다.

i++이나, ++i냐,
i--이냐, --i냐...
이것의 원리를 좀 알아 보고자 하는거 같다.

역시나 가장 기본은,
사용 후 더하느냐,
더한 후 사용 하느냐.

라고 보면 되겠지만
조금 자세히 파보자.

먼저 i++, ++i의 차이인데,
증가, 감소 연산자는 전위형태이든, 후위형태이든, 인자를 받지 않는(사용하지 않는) 구조이다.

그렇기 때문에 오버로딩을 하기 위해서 걸리는 매개변수의 타입이나, 갯수등으로 구별 하기가 까다로워 진 것이다.

이를 위해 약속한 것이,
전위는 그냥두고, 후위 형태는 int 타입의 인자를 받는 것으로 하자.
라고 약속하였다고 한다.

다음과 같이 말이다.

다음은, 전위, 후위 형태의 내부 구조이다.

쉽게 말해서 전위, 후위를 나누기 위해 후위의 경우 인자 int를 받고 있지만,
전혀 의미가 없다는 것을 알 수 있다.

이제 내부 구조를 조금 살펴 보면,
후위 구조의 경우 return 값이 const를 가지고 있다.
쉽게 말해서 i++++; 을 방지 하기 위해서 이다.
저 i++++을 사용한 의도가 뭘까?
i+=1 이후 계산 한 다음..? ++?
아니면 i +=2 이후 계산?
어떻게 생각해도 애매한 코드이다. 그런 부분을 일절 용납 하지 않겠다는 것이다.

마지막으로, ++i, i++ 뭐가더 빠를까?
물어볼 것도 없다. 당연히 ++i 가 더 빠른 것이다.
이리저리 뺑 돌아가긴 했지만, 결국 여기서 의도한 것은
가능하면 i++ 을 쓰지 말고 ++i을 써라,
어차피 후위 연산자를 사용하면, 전위 연산자를 지나칠 수 밖에 없기 때문이다.

Posted by 안식의후크




이번 항목은 타입변환에 대한 내용.

코드를 통해 문제점 부터 파악해 보자.




사실 코드만 보면 << 에 대한 연산자 오버로딩이 없기 때문에 안될거 같은데? 라고 생각하겠지만,
실제론 형변환이 이루어 지면서 출력이 된다.
이런 상황을 제거하기 위해, operator double가 아닌, 함수로써 변경을 하는 방법이 존재한다.


다음 예제를 보자.

다음과 같이, 암시적 변환을 사용하게 되었을 때는 원하지 않는 결과에 도출하게 된다.
물론 a == b[i]가 의도한 코딩이라면 상관없을지도 모르겠지만,
현재 상황에서 저 코드에 문제가 있다는 것을 시력이 좋거나,
런타임 후에 확인하거나,,
둘중 하나일 것이다.
코드를 하나하나 따라가 보면,
a 의 생성자에 10번,
operator==에 10번 들른다.
그 부분에 대해서는 항목 19에서 다시 설명한다고 한다.
자 문제는 파악 했고, 이제 저런 상황에서 우리가 원하지 않는 암시적 변환을 막고 싶다고 하였을 때,
어떻게 해야 할까? 답은 생각보다 쉬웠다.

explicit

이로써 이전에 if( a == b[i] ) 부분에서 컴파일 오류가 날것이다.
하지만 모든 문제가 해결된 것은 아니다.
비록 암시적 변환은 해결 됐지만,
명시적 타입 변환은 여전히 허용되는 것이다.
현재로썬 저런 어색한 부분에 대한 해결책은 언급하고 있지 않지만,
명시적 타입 변환이라고 해도, 이전에 이야기 했듯이 지나친 형변환은 지양하자는 말이 떠오르는 코드다.
이번 타입 변환과는 별개로, 2번째 if문에 존재하는 > > 사이의 공백에 대해 언급을 하고 있는데,
저곳에 공백을 넣지 않으면 operator >> 를 호출 한다고 하니, 주의하도록 하자.
(필자는 그냥 무조건 공백을 주는 습관을 가지고 있으니 괜찮다!)
이 후에는 explicit 를 지원하지 않는 컴파일러에서의 해결 방법을 이야기 하고 있는데,
안봐도 되지만, 내용이 프록시 클래스 라는 것에 대해 미리 이야기 하고 싶었던것 같다.
한번 그냥 훑어 보는 정도로 넘어가면 될듯.

Posted by 안식의후크




차암.. 이 부분은 읽으면 읽을 수록,
"아. 어쩌라고 ㅋㅋ"
라는 말이 절로 나온다.

쉽게 풀어 설명하면,


다음과 같은 클래스가 있다고 치자.
사용자는 무언가 생성할때 ID를 같이 초기화 하고 싶은것이다.
각 id는 중복 되서는 안되고, 고유의 id를 가지고 있다고 치자.
그렇기 때문에 생성할 때 id를 넣어 주는 식의 방법을 채택 하였는데,
문제는 이거다.

책에서는 여러 가지 방법들이 보여지는데,
이래저래 쭉 읽다 보면 결론은,
그냥 내비 둬라(?) ... 라는 결론이 나오게 되는데,
해결책의 첫번째에는, 생성을 객체의 배열을 포인터로써 생성한다는 방법인데,
사실 이 부분도, 결과적으론 최종 생성할때 생성자에 인자를 넣어 주는 방식이고,
(어찌 보면 괜히 메모리만 더 먹는거 같기도 하다.)
다음 부분은 기본 생성자를 생성하여 문제를 직접 해결하고,
추후에 값이 올바른지 그렇지 않은지 예외 조건을 넣으라는 것이다.
하지만 그 부분은 포퍼먼스가 많이 떨어지고, 다른 작업자가, 그런 예외 처리를 해주지 않을 수도 있다는 것이 단점,
근데 솔직히 내가 생각 했을 때 가장 편한건,
기본생성자를 하나 넣어주고, static이나, 전역 변수를 하나 잡아주어,
중복을 피하는 식으로 무작정 데이터를 삽입하는게 어떤가 싶은데,
내 예상 해결책은 다음과 같다.

하지만 이 부분에 문제점은 여전히 존재한다.
사실상, 어떤 값이 어떻게 들어 가게 될지 예측을 못한다는 것이다.
순차적으로 들어갈 수도 있고, 중간에 뛰엄뛰엄 들어갈 수도 있고..
의도한다면 중복된 값또한 넣을 수 있다는 것이다.

이 부분에 대해선 사실 정해진 답이 존재 한다기 보단,
생성자에 대해서 정확히 파악하고,
생길 수 있는 문제에 대해서 미리 한번 생각해 보라...
라는것을 말하고 있다고 생각한다.
Posted by 안식의후크




제목이 뭐랄까 복잡하지만, 내용을 보니 그정도 까진 아닌거 같다.

다형성이라는 정의를 좀 쉽게 설명하면,

"AAA 클래스를 상속받은 BBB 클래스가 있다.
그리고 AAA 클래스의 객체가 BBB 클래스를 접근하는 것이 가능하다. "

라고 표현 할 수 있겠는데...

아.. 써놓고 보니 쉽지 않은거 같기도 하고--;;

자세한 내용은 다형성에 대해서 "객체 포인터"라는 부분에서 정리를 예전에 해 두었으니 해깔리면

그걸 먼저 보는것이 나을 것 같다.

예제는 2가지정도 존재 하지만,
첫번째 예제만 봐도.
"아!... 위험하네." 싶다.


이런 상황이라고 하였을 때,
쉽게 프로그래머의 의도는, AAA arr[10]; 를 만든 이후,
그 값을 출력하기 위해 printAAA 를 만들었다고 보면 되겠다.
하지만,

다음과 같은 상황이 생겼을 때 문제가 발생하는 것이다.
물론 운이 좋게 컴파일러에서 미리 캐치를 해서, 값이 잘 보일 수도 있겠지만.
(실제로 내 컴파일러에서 출력에는 이상이 없긴 했다.)
문제는 delete 라던가, 다른 os나 pc 상황에서 분명 의도하지 않은 결과가 나올 수 있다는 것이다.
AAA의 메모리 크기는 8byte(예상) 라고 했을 때,
BBB의 메모리 크기는 8byte(AAA 클래스의 크기) + 8byte(BBB 클래스의 크기) 라는 것이다.
배열을 +1씩 증가 한다고 했을 때,
8byte씩 삭제 하다 보면,, 나머지 8byte는.. 과연 어디로 증발할지 아무도 모르는 것이다.
물론 BBB라는 클래스가 AAA를 상속받지 않거나, 존재하지 않는다면,
큰 문제가 없을 지도 모른다. 이와 관련되서 추후 항목에 다룬다고 하니, 그 때 다시 한번 확인하여 보자.
Posted by 안식의후크






먼저 static_cast, const_cast 부터 알아 보자.

다음은, dynamic_cast!!
마지막으로 reinterpret_cast이다.
사실 별거 아닌 부분들일 지도 모른다.
쉽게 생각해서 자신없으면 cast하지 않고, 있는 그대로만 잘 사용해도 왠만한 코드는 다 짤 수 있을 것이다.
하지만 알고 있는것과 모르는 것,
모르기에 사용하지 못하는것과, 알면서 사용하지 않는것은, 분명 차이가 있을 것이다.
cast부분에 대해서는 좀더 활용성을 찾아 보아야 할 것 같고,
이런 부분들은 추후 디자인 패턴에 대해 포스팅 할때 좀더 명확하게 집고 넘어 가려고 한다.
마지막으로 항목2 초반에 저자가 말하길, goto문과 같이 써서는 안되는 1급 기피대상이 cast(형변환) 이라고 한다.
하지만 무작정 안쓰는게 좋다기 보단, 적절한 상황에 적절하게...; 사용한다면 분명 안쓰는것 보단 나을 것이라 생각한다.
(애초에 사용해서는 안되는 것이라면 지원해 주는것 자체가 이상하지 않은가?)
이제 막 포스팅을 시작한 만큼, 더 많은 준비를 통해 좋은 발전의 결과를 내기 위해 노력할 생각이다.
Posted by 안식의후크




포인터와 참조자의 기본 개념부터 파악해 보자.
여러 좋은 예, 상황에 비유 할 수도 있지만 가장 큰 차이점과, 비슷한 점을 생각해 보았을 때
주소를 통해 접근, 같은 이름공간을 사용한 접근. 이라고 생각한다.

포인터든, 참조자든 사용하는 이유는 말 그대로 다른곳에 저장되어 있는 정보를 접근하여, 변경. 사용하기 위해서라고 생각하는데, 접근 하는 방식이 다르다고 보면 될 것 같다.

1. 참조자는 Null 의 개념이 존재 하지 않는다.
 즉, 생성과 동시에 이미 값이 존재하여야 한다는 것이다.


2. 상황에 따른 적절함이 필요 하다.
 



이것이 바로 함정이다. string& rs; 를 먼저 보고 생각한다고 하면, rs가 참조하는것을 s1에서 s2로 변형한것 같지만, 사실은 그렇지 않다. s2의 값을 s1에 대입해 버린것이다.

rs, s1, s2를 출력하면 모두다 같은 결과(Test2)가 나올것이다. 잘못됐다는 것이 아니라, 애초에 참조자를 쓴다는것 자체가 같은 이름 공간으로 취급하는 것이기 때문에,
s1 = s2; 를 의도한 것이라면 재대로 한것이 맞지만, 단순히 참조하는 대상을 바꾸기 위해서 사용 하였다면 크게 실수했다는 것이다.

마지막으로, 포인터를 썻을 때 어색해지는 구문일때 참조자를 사용하라고 되어 있지만.
이 부분에 대해서는 지금 구지 집고 넘어갈 필요는 없을 것 같다.
Posted by 안식의후크