• 분할컴파일

말그대로 프로그램을 파일로 나누어 컴파일한다는 뜻

 

수정부분의 파일만 수정 후 컴파일하면 되기 때문에 큰 규모의 프로그램을 보다 쉽게 관리 할 수 있다

 


  • #ifndef & #endif

ifndef는 if not defined 라는 의미로 어떠한 매크로 문구가 define되어 있으면

ifndef 과 endif사이의 코드를 실행한다는 의미다

 

정말 쉽게보면 if문에 bool형 조건을 단것과 같다

헤더파일을 여러번 포함시키는 실수를 피하기 위하여 사용하는 기법이다

 


  • Linkage
Linkage  : 연결
연결  :  사물과 사물을 서로 잇다

개념 : 변수의 속성중 하나로 파일과의 연결을 뜻하는 속성이다

이 사물과 사물을 프로그래밍 적으로 보면 파일과 변수라고 생각을 한다

 

이 속성은 세가지 항목으로 이루어져있다

[ 외부링크, 내부링크, 링크없음 ]

 

외부링크 - 말 그대로 현재 속한 파일뿐만 아니라 다른 외부 파일에서도 참조 할 수 있다 라는 속성

 

내부링크 - 현재 속한 파일에서만 참조 할 수 있다 라는 속성

 

링크없음 - 제한된 영역(ex. 스코프)에서만 참조 할 수 있다 라는 속성

 

★★★ Include.cpp 파일 이다, 밑에 코드와 이어짐

 

외부링크된 변수를 다른 파일에서 사용 할 때 필요한게 extern 이다

 

  • extern
extern 외부의, 바깥의

개념 : 다른 파일의 전역변수를 참조 한다는 참조선언이다

 

★★★ main.cpp 파일이다

extern을 사용해 위에 있었던 Include.cpp파일의 전역변수 A를 사용했다

 

참고로 static을 사용한 정적변수B는 내부링크 속성을 가지고 있으므로 extern을 선언해도 사용 할 수 없다

실행전에는 당연히 문제는 없다
하지만 실행결과

 


 

  • Static
static : (변화움직임이 없이) 고정된[고정적인]

 

개념 : 두가지 의미가 있다

 

밖에서 사용 할 경우 - 변수에 내부링크 속성을 사용한다라는 뜻

스코프 안에서 사용 할 경우 - 변수가 정적 기억 존속 시간을 가진다는 뜻

                                           (프로그램이 끝날 때 까지 존속)

 

(함수내부가 아닌)밖에서 Static을 사용한 변수를 정적변수 라 한다

(함수내부가 아닌)밖에서 Static을 사용하지 않은 변수를 전역변수(global) 라 한다

 

이제 밖이 아닌 스코프 안에 사용했을 경우에는 정적지역변수 라고도 하는데

변수는 프로그램이 끝날때까지 남아있으면서 사용된 그 스코프에서만 사용이 가능한데

 

언뜻보면 정말 쓸모없다고 생각이 들었는데 정적지역변수의 특성이 있었다

 

정적지역변수는 선언 부분이 계속 나와도 이미 선언이 되어있으면

초기화 하지 않고 이미 선언된 변수를 사용 할 수 있다

 

Include.cpp
main.cpp

이렇게 값이 계속 유지 되는걸 볼 수있다.

이는 한마디로 함수가 언제 호출 되든 값이 유지되는 변수다

 

정적지역변수는 함수가 다르면 식별자가 같아도 다른 변수로 인식된다

include.cpp
(좌) Test 함수의 정적지역변수A, (우) Test1 함수의 정적지역변수A

정적지역변수는 정말 신기했다ㅋㅋ

  • 오버로딩 분석(overload resoultion)

오버로딩, 함수템플릿, 함수템플릿 오버로딩 등 같은 이름의 함수가 여러개 있다면

컴파일러는 어떤 함수의 정의를 사용할것인가에 대해 C++는 선택과정을 가지고 있는데

이를 오버로딩 분석 이라 한다

 

오버로딩 분석은 함수 시그니쳐로만 판단을 하며 리턴형은 분석 대상이 아니다

 

 

각 단계는

 

1단계 : 호출된 함수의 이름과 동일한 함수들을 모아 목록을 만든다

 

2단계 : 매개변수의 개수와, 각 매개변수의 자료형이 맞는 함수만 뽑아낸다

여기서 자료형이 일치하지 않더라도 암시적 변환이 이루어지고 템플릿의 경우 구체화가 이루어 진다

 

3단계 : 가장 적당한 함수가 있는지 판단한다. 그 순서다

만약 정확하게 대응하는 함수가 두개 이상이거나 없으면 에러가 난다

 

일단 아직은 자세히 들어갈 필요보단 C++에서  여러 함수에 대응될때 매개변수를 통해 하나의 최적의 결과를

얻는다 생각 하면 될듯하다

 


  • decltype

decltype는 특정 식의 자료형을 추론할때 사용된다.

 

밑의 코드처럼 result에는 어떤 자료형이 들어와야 하는지 알 수 없다

+ 연산자는 기본으로 정수형 승급을 적용하여 결과는 정수형 타입이 되지만

따로 오버로딩도 가능하기에 어떤 타입이 될지 알수 없다

 

그에 따른 C++11의 해결책은 decltype 키워드 이다

이렇게 a+b의 자료형을 추론하여 자료형을 선언한다

 


  • 후위반환타입

C++11 에 생긴 Trailing Return Type(리턴 타입 추적 or 후위 반환 타입) 이라는 문법인데

말그대로 리턴타입을 추론해 내는 문법이다

 

사용법은 함수의 반환형을 auto로 사용하고 매개변수 괄호를 지나 -> 자료형 을 기술하면 된다

이런식으로 사용 된다.

 

double을 작성함으로 리턴타입추적의 결과를 double로 찾게된다

 

리턴자료형은 a+b

이 경우에는 decltype을 통해 리턴 자료형을 추론하였다고 볼수있다

 

밑의 코드처럼 꼭 템플릿이 아니라 일반 함수에도 사용 가능하다

[하지만 템플릿을 위해 만들어진 기능인듯하당]

 


기능은 auto와 매우 흡사하고 같이 연역관련 개념은 좀 깊이가 깊은듯 하여 따로 자세히 포스팅을 해야겠다

  • 함수 템플릿

c++에서 추가된 기능, 오버로딩작업을 자동화 해준다

 

Template은 한국어로 형판이라 한다

틀에 재료를 넣고 빼면 틀모양의 물건이 완성된다

틀에 다른 재료를 넣으면 각 재료로 만든 형체가 나온다

 

이 완성된 것은 모양은 같지만 재료는 다르다

여기서 재료는 자료형을 뜻하는것과 비슷하다고 생각한다

 

함수의 틀(모양)은 유지하되 다른 자료형(재료)으로 실행할수있다는 뜻으로 생각한다

 

템플릿은 함수템플릿, 클래스템플릿이 있으며 지금은 함수 템플릿만 정리한다

 

템플릿 설정은 template , class(혹은 typename) , < > 를 사용하여 설정한다

typename은 C++98에서 추가되었고 데이터형을 나타낸다는 사실을 더 분명하게 알려준다

이 템플릿 설정에 있어서 typename과 class는 일단 같은 기능을 한다

 

 

위의 템플릿함수를 사용시 사용할 자료형을 기술해야줘야하는데 (기술하는것을 명시적 구체화라 한다)

매개변수로 인해 자료형이 추론이 가능하다면 생략해도 좋다 (추론하는것으로 암시적 구체화라 한다)

매개변수 1로 인해 int형을 사용한다는걸 추론할수 있음

 


  • 템플릿 오버로딩

일반적인 오버로딩을 하듯 사용하면 된다

 

다만 주의할것은

이렇게 템플릿함수와 일반함수가 같은 함수처럼 보여도

오버로딩과는 별개로 다른 독립적인 함수임을 알아야한다

 


  • 구체화
구체 具體
사물이 직접 경험하거나 지각할 수 있도록 일정한 형태와 성질을 갖춤.

 

밑의 코드처럼 함수 템플릿을 작성하기만 한다고 실제 함수의 정의가 생성되는건 아니다

 

어떤 자료형을 사용할것이라고 구체적으로 기술한 템플릿을 사용하면(구체화)

그때! 기술한 자료형을 토대로 함수의 정의가 생성된다 (생성되는 시기는 호출되는 런타임이 아니라 컴파일 타임이다)

 

이를 '구체화' 라 한다

 

구체화에는 명시적 구체화, 암시적 구체화가 있는데

 

명시적 구체화는 직접 자료형을 써 넣어 구체화 하라고 지시하는 의미를 가진다

두가지 방법이 있는데

 

호출하지 않는 방법과 호출하는 방법이 있는데

1이 호출하지 않는 방법이고,

2가 호출하는 방법이다

 

호출할시에 <> 이 꺽쇠모양은 템플릿함수를 사용한다는 의미도 있다

템플릿함수로 호출이되어 일반함수를 호출하지않는다

 

암시적 구체화

Test(1); 꺽쇠(<>)에 명시적인 자료형을 기술하지 않고 매개변수로 자료형을 추론하여

해당 자료형을 토대로 구체화하는 방법이다

명시적 구체화와 함께 정리했다

 

정리하면서 뭔가 구체화가 인스턴스화와 같다고 느꼈다

무언가 실체화 되는 느낌이라고 생각하면 될듯하다

 

 

템플릿 함수

컴파일 타임에 구체화 되어 만들어진 함수를 '템플릿 함수' 라 한다

 

 


  • 명시적 특수화

[템플릿 특수화는 두가지가 있다 명시적 특수화, 부분적 특수화 함수 템플릿에서는 명시적 특수화만 가능하다]

특수 特殊
어떤 종류 전체에 걸치지 아니하고 부분에 한정됨. 또는 그런 것.

 

템플릿에서 특수화는 저 사전적의미를 빌리면 템플릿을 여러 자료형에 속하게하지 않고 지정 해주는 뜻 이라 생각한다

(자료형을)지정하여 그 지정된 자료형이 매개변수로 들어오면 그에 맞게 실행하는 것이다

 

한마디로 int형으로 특수화를 해놨을 때

int형으로 매개변수가 들어온 함수 호출이 있으면

따로 구체화하지말고 특수화 해놓은걸 사용해라 이런 느낌이다 

 

이 명시적 특수화는 어느 부분에서 필요성을 느끼게 되냐면

특정 자료형이 매개변수로 들어올때 다른 코드로 실행이 되게 하고싶을때 나타난다

 

이 특수화 방법은

함수 매개변수 개수가 같아야하고 반환형도 동일해야 한다

 

매개변수가 45인 int형은 명시적 특수화된 함수로 실행이 되었고

매개변수가 2.5f 인 float은 원형으로 실행이 되었다

 

덧붙여서 일반함수, 함수템플릿, 명시적 특수화된 함수 템플릿 이 세가지가 같은 호출조건을 가지고 있을때

우선순위가 있다

 

1. 일반함수 ── 2. 명시적 특수화된 함수 템플릿 ── 3. 함수 템플릿 

 

순이다

 

명시적 특수화와 명시적 구체화의 차이는 졸라 헷갈렸는데

 

명시적 특수화는 특정 자료형에 따라 다른 코드의 예외를 작성할 수 있는 것이고

명시적 구체화는 원본 코드 그대로의 특정 자료형에 대한 함수 정의를 만들라는 것이다

 

그리고 문법적으로 특수화는 template<> ,구체화는 template 의 차이가 있다


  • 특수화

암시적 구체화, 명시적 구체화, 명시적 특수화 이 모두를 특수화라 칭한다

 

  • 배열참조형

참조형을 담는 배열은 생성할 수 없다

 

단 배열자료형의 참조형은 가능하다

 


  • 디폴트 매개변수

C++에서 새로 생겨났으며

 

매개변수에 기본으로 사용하는 값을 지정하여

함수 사용시 설정한 해당 매개변수를 기술하지 않으면 설정한 값으로 매개변수가 입력되는 기능

 

밑의 int b처럼 기본값을 설정해주면 된다

 

디폴트 매개변수은 규칙은 무조건 오른쪽에서 왼쪽으로 기술해야한다

 


  • 오버로딩

같은 함수의 이름으로 다른 매개변수, 다른 함수내용 을 정의 할 수 있는 기능

 

이 오버로딩은 객체프로그래밍의 다형성을 나타내는 기능중 하나이다

이 설명을 프로그래밍으로 나타내면

같은 종의 생물 = 같은 식별자

크기, 형태, 색깔 = 매개변수 리스트, 반환 자료형, 함수 내용  이라고 생각한다

 

식별자는 같지만 매개변수, 내용이 다르다

 

오버로딩을 할 때 주의 할 점은 매개변수 리스트는 필수로 무조건 달라야한다

 

반환 자료형이나 함수내용이 달라도 매개변수 리스트가 같으면 성립이 되지 않는다

 

이와 몇가지로 안되는 경우가 있는데

 

보통 함수에 이미 본문이 있을 때 이다

  • 매개변수의 const

코드상으로는 문제가 없지만 실행시 오류가 난다

 

이유는 같은 코드라고 컴파일러가 인식하기 때문

 

이는 int a나 const int a나 lvalue, rvalue모두 가능한 공통점 때문에 같은 코드라고 인식하는듯 하다

 

단 참조일 경우에는 다르다

참조일 경우에는 lvalue, rvalue 확실히 나누어지기 때문에 가능한 듯하다

 

 

※클래스의 멤버함수에서는 이런식으로 가능하다

 

  • * 와 [ ]

내가 생각하기로는 [ ]은 매개변수로 들어갈때 컴파일러가 포인터형으로 변환하는데

 

이때문에 같은 코드로 인식되어 실행이 불가능한 듯하다

 


  • 이름장식

c++은 오버로딩된 함수중 어떤것이 맞는지 어떻게 추적하냐면

이름장식(Name mangling)을 사용한다고 한다

 

함수 원형에 지정되어 있는 형식을 암호화 한다고 한다

 

예를들어

long Test(int) 를 암호화로 ?test@@YAXH@z

이런식으로 매개변수의 개수와 데이터형을 암호화한다고 한다

[컴파일러마다 암호 규칙이 다르다고한다]

 

이렇게 다른 암호화명으로 찾는듯 하다

  • inline함수

inline함수는 프로그램의 실행 속도를 높이기 위해 c++에서 새로 보강된것

 

함수가 하나 생성되면 함수의 시작 주소가 있을것이며

함수가 호출 될때 그 시작주소로 가서 실행 후 다시 원래 있던 주소로 돌아갈것이다

 

이를 더 자세히 하면

 

1. 함수 호출 명령

2. 함수 호출 명령 다음의 코드 주소를 메모리에 저장 [함수 종료 후 다시 돌아와야하니까]

3. 호출하려는 함수의 매개변수 복사 [파라미터에 넣어야하니까]

4. 호출하려는 함수의 주소로 점프

5. 함수 코드 수행

6. 함수 종료시 함수의 리턴값을 레지스터에 복사

7. 저장해 두었던 코드 주소로 점프

 

이러한 과정들이 있는데

inline은 이러한 문제를 어느정도 해결해준다

 

바로 함수를 호출할때 원본함수코드를 그냥 그자리에 붙여넣어서 

이동할 필요 없이 그 자리에서 읽고 처리한다

define과 비슷한 부분이다

 

이렇게 작성한 코드를 inline화 시키면

 

이런식으로 원본 코드가 온다는 말이다

 

inline의 사용법은 inline 이라는 키워드를 함수의 선언이나 정의 앞에 붙여주면 된다

 

inline이 속도는 굉장히 빨라지겠지만 만약 함수의 크기가 크다면

붙여지는 코드의 양도 그만큼 커져 프로그램이 무거워질 것이다 [ ※재귀함수는 불가능 ]

그렇기 때문에 그 기준을 잘 잡아야 하는데

 

이 기준은 다행히도 컴파일러가 알아서 해준다

얼마나 알아서 잘 해주냐면

 

우리가 inline키워드를 사용해도 컴파일러 판단에 부합하지 않으면 inline화 해주지 않는다

우리가 inline키워드를 사용하지 않아도 컴파일러 판단에 inline화 해준다

 

그러므로 우리가 inline키워드를 사용한다는것은 약간 요청보단 이건 어때? 라는 권유의 느낌 같다.

 

그리구 추가로 inline함수의 함수포인터를 사용해서 함수가 호출되었을때는 일반함수로 호출이 된다

 

이쯤 보면 매크로와 상당히 비슷한데

차이랄게 있다면

매크로는 단순히 코드를 변환시키는거지 값을 전달하지않는다

매크로 함수같은경우 값이 전달되는게아니라 문자 치환이여서

++a * ++a 가 되므로 "++" 연산자가 두번 실행된 후 곱셈이 진행되어 3 * 3으로 9가 나온다.

 


  • 참조변수

c++에 새로운 복합자료형이다

 

reference라고도 하며 미리 정의된 어떤 변수의 식별자 대신 쓸 수 있다

 

이 대신 사용한다는 것은 주소를 참조하여 사용한다는 의미이다 => 복사비용문제 해결

 

생성은 &를 붙여 생성한다

오른쪽 처럼 선언과 동시에 정의를 해주지않으면 생성 할 수 없으며

나중에 참조하는 변수를 바꿀수 없다

 

이 참조변수의 주된 용도는 매개변수에 사용하는데

 

기존 함수가 호출될때 매개변수에 들어온 값을 복사하여 사용하는데

이 참조형을 매개변수로 사용할시에 함수는 같은 주소를 가지고 있는 매개변수를 받기때문에 원본 데이터를 다룰수있다


만약 참조형에 다른 자료형이나 상수가 들어가면 에러가 난다

 

하지만 const를 사용하면 허용이 된다

이는 const일 경우 컴파일러는 임시변수를 생성하기 때문이다

long a를 int형으로 변환시켜 만든 임시변수 를 ra1가 참조하고

ra2 에 들어가는 상수 32를 가지고 있는 int형 임시변수 를 ra2가 참조하게 만든것이다

 

참조형은 참조 대상과 주소 값이 같다는 특성 때문에 참조 대상의 '별칭(alias)'이라고도 불린다. 

 

나무라서 좀 그렇지만 배울게 많다..

https://namu.wiki/w/%EC%B0%B8%EC%A1%B0%EC%97%90%20%EC%9D%98%ED%95%9C%20%ED%98%B8%EC%B6%9C

 

  • 함수포인터

함수도 주소를 가지고 있다 그 주소는 함수의 기계어 코드 시작주소를 가르킨다

괄호없이 함수의 이름만 작성하면 주소가 된다

이 함수 주소를 담는 포인터형도 있는데

반환형, 매개변수타입을 함수원형 처럼 써주면 되며, auto를 이용해 편하게 사용할 수 있다

책에서 auto는 배열처럼 리스트 형식을 초기화할 때는 사용할 수 없다고 하는데

기본 우리가 알던 배열 형식은 아니지만 initializer list로 적용이 된다

initializer list로 실행되는 모습

 

함수포인터의 자료형을 다루는걸 알았으니 함수의 매개변수에도 넣을 수 있다

 

함수포인터의 호출 방법은 두가지가 있다

 

1. 포인터이기에 *를 사용하여 함수에 접근해야한다

2. 함수이름이 그 함수를 지시하는 포인터이므로 그 함수를 가르키는 포인터도 함수이름처럼 사용해야한다

위 두가지가 모두 논리적으로 맞기에 둘다 허용된다

 

 

  • 함수와 2차원 배열

함수에 2차원 배열을 매개변수로 넣는것에 대해 설명하는 부분

 

함수의 원형 부분에 2차원 배열의 자료형을 기술할때 행의 개수는 필수로 입력하는게 핵심이다

7

https://ddidding.tistory.com/31

더블포인터에 이차원 배열의 이름이 대입되지 않는다 항목과 비슷한 개념이다

 


  • 함수와 문자열

문자열을 매개변수로 넣으려면 문자열의 첫번째 주소를 넣는다

C 스타일 문자열 예시

 

 


  • 함수와 구조체

구조체는 작성에 따라 메모리가 작을수도 있고 클수도있다

Test를 호출했을 경우 a가 복사되어 st에 대입된다

지금은 a의 크기가 작기에 이렇게 pass by value를 사용해도 괜찮지만

만약 a 크기가 크다면 이 복사과정이 부담이 될 수 있다

 

그래서 주소를 전달해 줄 수 있다

주소를 넘기는 방식중 passing by reference를 C++에서 제시한다고 한다

이건 뒤에 나오니까 뒤에서 정리한다

 

 


  • 함수와 std::array

stl array를 매개변수로 사용하고 Range based for loop를 사용하여 출력

 

 


  • 재귀호출

함수가 자기 자신을 호출할 수 있다 이걸 재귀호출이라 한다

 

간단한 로직은 if문을 통해 끝내는지, 자기자신을 호출하는지 분기를 나눈다

간단한 계승기능

위처럼 재귀함수는 for문으로도 서로 변환이 가능하다

 

재귀함수는 간결한 코드로 표현이 가능하나 스택에 계속 데이터가 쌓여 반복이 커진다면 stack over flow가 발생한다

 

알맞은 때에 사용해야 한다. 이 알맞은 때는 경험으로 이루어지면 될듯싶다

  • 더블포인터에 이차원 배열의 이름이 대입되지 않는다
더보기

 

배열의 이름은 첫번째 원소의 주소이다

a의 첫번째 원소는 int형의 주소, 그러므로 포인터에 대입이 가능하다

 

aa의 첫번째 원소는 &(aa[0][0])이 아니라 &(aa[0]) 이다

예로 

첫번째 원소는 int형을 5개 가진 aa[0]이고

두번째 원소는 int형을 5개가진 aa[1]이다.

고로 aa는 int[5]의 배열이다

 

그럼 &(aa[0]) 의 자료형은 int (*) [5](int형 5개를 가진 포인터)

int형의 더블포인터 와 int[5]를 가진 포인터는 다르다

 

paa는 int*의 주소이다(int**)

그러므로 int(*)[5]와 int** 는 다른 자료형이기에 대입이 되지않는다 

+1을 하면 더해지는 주소의 양이 다르다

 

이게 헷갈리는 이유중 하나는 둘다 참조를 두번하면 int형이 나오는게 동일해서일듯싶다

밑에서 aa[0][0]과 paa[0][0]의 자료형은 같다

aa[0]과 paa[0]의 자료형은 위에서처럼 다르다

 

배열자료형을 잊지말장

 

 


  • 포인터는 1차원배열과도 같다고 생각한다

+ Recent posts