◆인라인 함수
●시간을 효율을 위해, 일반적인 함수의 호출 과정을 거치지 않고 호출된 자리에 코드를 넣는 방식이다.
- 함수 선언 앞에 inlilne이라는 키워드를 붙인다.
- 함수 정의 앞에 inline이라는 키워드를 붙인다.
- 인라인 함수는 재귀 호출이 허용되지 않는다.
- 매크로에 비해 인라인이 문법적 자유를 가지고 있어 인라인을 써야 한다.
int a = 2;
cout<<SQUARE(a++); // a++연산이 두번 되어 3*3이 아니라 4*4가 된다.
◆참조 변수
●주소를 나타내기 위한 & 기호를 통해 참조 변수를 만들 수 있다.
int home;
int & homeAddress = home;
- 여기서는 &가 주소 연산자가 아니라, 데이터형 식별자의 일부로 사용된 것이다.
- 참조를 선언할 때 참조 변수를 함께 초기화를 해주어야 한다.
- 연결된 참조 변수는 다른 것과 연결될 수 없다. (const와 비슷하다.)
int & homeAddress1 = home;
int * const homeAddress2 = home; //본질적으로 같다. (homeAddress1 == *homeAddress2)
●참조는 주로 함수의 매개변수로 사용된다.
- 매개변수로 주면 값을 빠르게 전달이 가능하되, 메모리 위치를 다르게 할 수 없기 때문이다.
●포인터와의 차이점
- 포인터를 이용하는 경우에는 함수가 p와 q를 사용할 때마다 내용 참조 연산자인 *를 사용해야 한다는 것이다.
▷▷▷▷▷참조 매개변수는 구조체나 클래스와 같이 덩치 큰 데이터를 다룰 때에나 유익하다.
◆lvalue란 무엇인가?
●참조가 가능한 데이터 객체이다.
●변수, 배열의 원소, 구조체의 멤버, 참조 또는 역참조 포인터는 lvalue이다.
●참조가 const로 선언되어 있으면, C++는 필요할 때 임시 변수를 생성한다. 기본적으로, 형식 매개변수가 const 참조로 되어 있는 함수는, 데이터형이 일치한지 않는 실제 매개변수를 전달받았을 때, 정보를 값으로 전달받는 전통적인 방식을 따른다. 즉 임시 변수를 사용하므로 원본 데이터를 변경하지 않는다.
●참조 매개변수를 상수 데이터에 대한 참조로 선언하는 이유
- const를 사용하면, 실수로 데이터 변경을 일으키는 프로그래밍 에러를 막을 수 있다.
- 함수 원형에 const를 사용하면, 함수가 const와 const가 아닌 실제 매개변수를 모두 처리할 수 있지만, 함수 원형에 const를 생략한 함수는 const가 아닌 데이터만 처리할 수 있다.
- const 참조를 사용하면, 함수가 자신의 필요에 따라 임시 변수를 생성하여 사용할 수 있다.
●참조를 리턴하는 함수는 실제로 참조가 되는 변수에 대한 alias(별명) 파일이다.
●참조를 리턴할 때 주의할 점
▷함수가 종료할 때 수명이 함께 끝나는 메모리 위치에 대한 참조를 리턴하지 않도록 조심하는 것이다.
▷이 문제를 피하는 방법은, 함수에 매개변수로 전달된 참조를 리턴하는 것이다.
●const를 매개변수 혹은 lvalue로 사용하려면, 이 값이 변하지 않음을 보장해주기 위해 const로 선언된 변수에 대입해주어야 한다.
◆초기 포맷팅 상태 저장
ios_base::fmtflags initial;
initial = os.setf(ios_base::fixed); //초기 포멧팅 상태 저장.
os.precision(0);
os.setf(ios::showpoint);
os.precision(1);
os.width(5)
os.setf(initail); //초기 포멧팅 상태 복원
◆참조 매개변수를 쓰는 이유
- 호출 함수에 있는 데이터 객체의 변경을 허용하기 위해
- 전체 데이터 객체 대신에 참조를 전달하여 프로그램의 속도를 높이기 위해
- ※이것은 단지 지침일 뿐이다.
●함수가 전달된 데이터를 변경하지 않고 사용만 하는 경우:
- 데이터 객체가 기본 데이터형이나 작은 구조체라면 값으로 전달한다.
- 데이터 객체가 배열이라면 포인터가 유일한 선택이므로 포인터를 사용한다. 포인터를 const를 지시하는 포인터로 만든다.
- 데이터 객체가 덩치 큰 구조체라면 const 포인터나 const 참조를 사용하여 프로그램의 속도를 높인다. 이것은 구조체나 클래스 설계를 복사하는 데 드는 시간과 공간을 절약한다.
- 데이터 객체가 클래스 객체라면 const 참조를 사용한다. 클래스 설계 자체가 흔히 참조를 사용할 것을 요구한다. 이것이 C++에 const 기능을 추가한 주된 이유이기도 하다. 클래스 객체 매개변수의 전달은 참조로 전달하는 것이 표준이다.
●함수가 호출 매개변수의 데이터를 변경하는 경우 (매개변수의 deep copy)
- 데이터 객체가 기본 데이터형이면 포인터를 사용한다.
- 데이터 객체가 배열이면 유일한 선택은 포인터를 사용하는 것이다.
- 데이터 객체가 구조체이면 참조 또는 포인터를 사용한다.
- 데이터 객체가 클래스 객체이면 참조를 사용한다.
◆디폴트 매개변수
- 함수에 들어가는 매개변수의 기본값을 지정해준다.
- 매개변수 리스트를 사용할 때 디폴트 매개변수가 있는 매개변수를 오른쪽에 첨가해야한다.
◆이름 장식(Name Decoration)
- 컴파일러는 자신의 사용을 위해 알아보기 어려운 내부형식으로 함수이름을 바꾼다.
◆함수 템플릿
- 임의 데이터형으로 함수를 정의하는 것을 허용한다.
template <class Any> //Any 대신 typename을 작성해도 된다.
void Swap(Any &a, Any &b){
Any temp;
temp = a;
a=b;
b=temp;
}
- 장점 : 여러 개의 함수 정의를 더 간단하고 더 신뢰성있게 생성한다.
◆템플릿의 오버로딩
●3세대 특수화(ISO/ANSI C++표준)
- 함수 이름이 하나 주어지면, 사용자는 템플릿이 아닌 함수(일반 함수), 템플릿 함수, 명시적 특수화 템플릿 함수를 가질 수 있다. 또한 이 모든 것들의 오버로딩 버전도 가질 수 있다.
- 명시적 특수화를 하기 위한 원형과 정의 앞에 template <>가 와야 한다. 그리고 그 특수형의 이름을 서술해야 한다.
- 특수화는 템플릿을 무시하고, 템플릿이 아닌 함수는 특수화와 템플릿 둘 다를 무시한다.
//job형을 위한 명시적 특수화
template <> void Swap<job>(job &,job &)
◆템플릿의 구체화(instantiation) 그리고 암시적 구체화(implicit instantiation)
- 모든 자료형의 템플릿이 구체화 되지는 않는다. 코드상에서 int형으로 Swap()을 사용하였을 경우 int형을 사용하는 Swap()을 구체화 하게 만든다.
- 이러한 방식을 암시적 구체화(implicit instantiation)라고 한다.
- 암시적 구체화, 명시적 구체화, 명시적 특수화를 모두 특수화(specialization)라고 한다.
- 모두 구체적인 데이터형을 사용하는 함수 정의를 나타낸다는 것이다.
template <> void Swap<job>(job &, job &) //job을 명시적 특수화
template void Swap<char>(char &, char &) //char을 위한 명시적 구체화
short a.b;
Swap(a,b); //short를 위한 암시적 템플릿 구체화
job c,d;
Swap(c,d); //job을 위한 명시적 특수화를 사용한다.
char e,f;
Swap(e,f); //char를 위한 명시적 템플릿 구체화를 사용한다.
◆템플릿의 정확한 대응과 최선의 대응
●정확한 대응을 위해 허용되는 사소한 변환
변환 전 실제 매개변수 | 변환 후 형식 매개변수 |
Type | Type & |
Type & | Type |
Type [] | * Type |
Type (argument-list) | Type (*) (argument-list) |
Type | const Type |
Type | volatile Type |
Type * | const Type * |
Type * | volatile Type * |
'C++ > C++' 카테고리의 다른 글
10. 객체와 클래스 (0) | 2023.07.17 |
---|---|
9. 메모리 모델과 이름 공간 (0) | 2023.07.14 |
7. 함수 - C++의 프로그래밍 모듈 (0) | 2023.07.10 |
6장 조건문 (0) | 2023.07.02 |
5장 반복문과 cin 메모 (0) | 2023.07.01 |