※ 참조 변수를 사용해야 하는 경우
- 참고하고자 하는 어떤 객체를 미리 알고 있을때
- 중간에 참조하는 대상을 바꿀 일이 결코 없을때
- 포인터를 사용하면 문법상 의미가 어색해지는 연산자를 구현할때(필자는 주로 STL 컨테이너를 사용할때임)
아래는 필자가 15년 09월 쯤에 제작한 클래스다.
operator>>들의 인자를 보면 죄다 참조 변수로 되어 있는데, 이처럼 참조는 클래스를 설계할 때도 필수적으로 사용된다.
※ 참조 변수를 사용해야 하는 경우
- 참고하고자 하는 어떤 객체를 미리 알고 있을때
- 중간에 참조하는 대상을 바꿀 일이 결코 없을때
- 포인터를 사용하면 문법상 의미가 어색해지는 연산자를 구현할때(필자는 주로 STL 컨테이너를 사용할때임)
아래는 필자가 15년 09월 쯤에 제작한 클래스다.
operator>>들의 인자를 보면 죄다 참조 변수로 되어 있는데, 이처럼 참조는 클래스를 설계할 때도 필수적으로 사용된다.
※요약
인라인 함수는 프로그램의 실행 속도를 높이기 위해 추가된 기능이며 C언어의 매크로 함수와 비교된다.
(개발자 입장에서)일반 함수와 인라인 함수의 가장 큰 차이점은 함수의 호출 방식이다. 일반 함수의 호출 방법은 프로그램 실행 중 함수를 실행해야하면 해당 함수의 주소로 점프시켰다가, 함수의 처리가 종결되면 다시 원래의 자리로 돌아오는 것이다. 이렇게 앞뒤로 점프를 수행하고, 점프할 위치를 기억하려면 함수를 사용하는데 시간이 많이 걸린다.
인라인 함수는 컴파일된 함수 코드가 프로그램의 코드 안에 직접 삽입되어진다. 이 말은 컴파일러가 함수를 호출하는 대신, 그에 대응하는 함수 코드로 대체한다는 것을 의미하며 함수 호출없이 삽입된 함수 코드를 그 자리에서 처리하므로 해당 함수를 수행하기 위해 프로그램이 다른 주소로 점프했다가 되돌아 올 필요가 없어 속도면에서 유리하다.
※특징
- 인라인 함수를 사용하려면 함수 선언 앞에 inline이라는 키워드를 붙이거나 함수 정의 앞에 inline이라는 키워드를 붙인다.
- 클래스 멤버 함수가 inline을 사용하려면, 함수 정의의 위치가 *.h에 있어야 한다. 안 그러면 확인할 수 없는 외부 참조라고 뜬다.
- 프로그래머가 inline 선언을 해도 컴파일러가 인라인화를 거부할 수 있다.
- 프로그래머가 inline 선언을 안 해도 컴파일러가 인라인화를 할 수 있다.
- 함수의 덩치가 크거나 재귀호출이면 inline 요구를 거절하는 컴파일러도 있다.
- 함수 코드의 수행 시간이 짧고 빈번하게 호출되는 함수가 아니라면, 인라인 함수로 인한 절대적인 시간 절약은 그다지 크지 않다.
※장점
- 함수가 인라인화 되어 성능의 향상으로 이어질 수 있다.
※단점
- 메모리 사용 측면에서는 인라인 함수가 일반 함수보다 불리하다. 이유는 어떤 프로그램에서 인라인 함수를 열 번 호출한다면, 프로그램은 그 함수의 사본을 프로그램의 코드 안에 열 번이나 삽입해야 하기 때문이다.
- 매크로 함수와 달리 자료형에 독립적이지 못 하다. 단, 템플릿을 이용하면 자료형에 독립적으로 사용할 수 있다.
※예제
#include <iostream> using namespace std; inline void Test( int nNum1 ); int main( ) { Test( 2 ); return 0; } void Test( int nNum1 ) { int nResult = nNum1; }
[C++] 04. 매개변수의 디폴트 값 (0) | 2014.01.22 |
---|---|
[C++] 03. 함수 오버로딩 ( function overloading ) (0) | 2014.01.22 |
[C++] 02-02. scanf를 대신하는 cin (0) | 2014.01.22 |
[C++] 02-01. printf를 대신하는 cout (0) | 2014.01.21 |
[C++] 01. Hello World (0) | 2014.01.21 |
※요약
매개변수의 디폴트 값이란 함수를 호출할 때 매개변수(전달인자)를 생략할 경우, 지정된 디폴트 값을 넣어서 함수를 호출하는 걸 말한다.
※특징
- 디폴트 값은 함수 원형 선언시 설정한다.
- 디폴트 값은 오른쪽에서 왼쪽 순서로 설정해야 한다.
※예문
int Test( int nNum1, int nNum2, int nNum3=30 ) |
O |
int Test( int nNum1, int nNum2=20, int nNum3=30 ) |
O |
int Test( int nNum1=10, int nNum2=20, int nNum3=30 ) |
O |
int Test( int nNum1=10, int nNum2, int nNum3 ) |
X |
int Test( int nNum1, int nNum2=20, int nNum3 ) |
X |
int Test( int nNum1=10, int nNum2=20, int nNum3 ) |
X |
※예제
#include <iostream> using namespace std; //함수 선언에 디폴트 값을 설정한다. void Test( int nNum1, int nNum2=20, int nNum3=30 ); int main( ) { Test( 2 ); //Test( 2, 20, 30 )와 같다. Test( 2, 8 ); //Test( 2, 8, 30 )와 같다. Test( 2, 7, 9 ); //Test( 2, 7, 9 )와 같다. return 0; } //함수 정의에는 디폴트 값을 설정 안 해도 된다. void Test( int nNum1, int nNum2, int nNum3 ) { int nResult = 9; }
[C++] 05. 인라인 함수 - inline function (1) | 2014.01.23 |
---|---|
[C++] 03. 함수 오버로딩 ( function overloading ) (0) | 2014.01.22 |
[C++] 02-02. scanf를 대신하는 cin (0) | 2014.01.22 |
[C++] 02-01. printf를 대신하는 cout (0) | 2014.01.21 |
[C++] 01. Hello World (0) | 2014.01.21 |
※요약
함수 오버로딩이란, 서로 다른 여러 개의 함수가 하나의 이름을 공유(연결)하는 것이다.
함수 오버로딩은 서로 다른 데이터형을 대상으로 하지만 기본적으로는 같은 작업을 하는 함수들에만 사용하는 것이 좋다.
※특징
- C++은 함수 호출 시 함수의 이름과 전달되는 인자의 정보를 참조하여 호출할 함수를 결정한다.
- 함수 오버로딩의 열쇠는 전달 인자이며, 이것을 함수 시그내처( function signature )라고 한다.
- 함수 오버로딩의 조건은 매개 변수의 자료형, 매개 변수의 개수, 매개 변수의 순서 등이다.
※예문
↓ (O)매개 변수의 자료형이 다르므로 함수 오버로딩 성립
void print( float fNum ) { . . . } |
void print( int nNum ) { . . . } |
↓ (O)매개 변수의 개수가 다르므로 함수 오버로딩 성립
void print( int nNum1 ) { . . . } |
void print( int nNum1, int nNum2 ) { . . . } |
↓ (X)반환형의 차이는 함수 오버로딩의 조건에 포함되지 않는다.
void print( int nNum1 ) { . . . } |
int print( int nNum1 ) { . . . } |
※예제
#include <iostream> using namespace std; void print( int nNum ); void print( int nNum1, int nNum2 ); void print( float fNum ); void print( double dNum ); int main( ) { print( 5 ); print( 6, 8 ); print( 3.14f ); print( 50.5 ); return 0; } void print( int nNum ) { cout << nNum << endl; } void print( int nNum1, int nNum2 ) { cout << nNum1 << " and " << nNum2 << endl; } void print( float fNum ) { cout << "float : " << fNum << endl; } void print( double dNum ) { cout << "double : " << dNum << endl; }
[C++] 05. 인라인 함수 - inline function (1) | 2014.01.23 |
---|---|
[C++] 04. 매개변수의 디폴트 값 (0) | 2014.01.22 |
[C++] 02-02. scanf를 대신하는 cin (0) | 2014.01.22 |
[C++] 02-01. printf를 대신하는 cout (0) | 2014.01.21 |
[C++] 01. Hello World (0) | 2014.01.21 |
※요약
C++의 cin은 키보드로 입력한 값을 저장할 변수가 받아들이는 형태로 알아서 바꿔 저장한다.
cin은 iostream 파일에 입력 스트림을 나타내는 객체로 정의되어 있다.
※특징
- cin은 "씨 인"이라고 발음한다.
- cin은 문자열, 수, 문자 등 다양한 데이터형을 서식문자 없이 변수형에 맞게 자동으로 입력해 준다.
- cin에서 >> 표시는 입력 연산자하고 부른다.
- 입력 연산자로 >>를 선택한 이유는 정보가 흐르는 방향을 연상시키기 위한 것이다.
※예제
#include <iostream> using namespace std; int main( ) { int nInputNum; cout << "임의의 수를 입력하세요 : "; cin >> nInputNum; cout << "입력한 수는 " << nInputNum << "입니다" << endl; return 0; }
[C++] 05. 인라인 함수 - inline function (1) | 2014.01.23 |
---|---|
[C++] 04. 매개변수의 디폴트 값 (0) | 2014.01.22 |
[C++] 03. 함수 오버로딩 ( function overloading ) (0) | 2014.01.22 |
[C++] 02-01. printf를 대신하는 cout (0) | 2014.01.21 |
[C++] 01. Hello World (0) | 2014.01.21 |
※요약
C++의 cout은 C언어의 printf와 달리 출력할 것이 문자인지 정수인지 소수인지 자동으로 알아차리고 출력한다.
위와 같은 것이 가능한 이유는 객체 지향 기능을 가지고 있기 때문에 가능한 것이며, 연산자 오버로딩의 한 예이다.
※특징
- cout은 "씨 아웃"이라고 발음한다.
- cout은 문자열, 수, 문자 등 다양한 데이터형을 서식문자 없이 자동으로 출력해 준다.
- cout에서 << 표시는 왼쪽 시프트 연산자라고 부르지 않고 삽입 연산자 라고 부른다.
- << 표시는 명령문이 그 문자열을 cout에 전달한다는 것을 뜻하며 <<가 나타내는 방향이 정보의 흐름을 상징한다.
- 개행을 할 때에는 조정자 endl나 '\n'을 사용한다.
※삽입 연산자 <<에 오버로딩 되어 있는 기본 데이터형들
unsigned char
signed char
char
short
unsigned short
int
unsigned int
long
unsigned long
float
double
long double
const signed char *
const unsigned char *
const char *
void *
※cout의 진법 변경
printf의 경우 8진법이나 10진법, 16진법을 출력할 때 각각 %o, %d, %x를 사용하는 데
cout의 경우는 oct, dec, hex 조정자를 사용하여 각 진법을 출력한다.
#include <iostream> using namespace std; int main( ) { int nNum(14); //10진법 출력 cout << "10진법 : " << nNum << endl; //8진법 모드로 설정 cout << oct; cout << "08진법 : " << nNum << endl; //16진법 모드로 설정 cout << hex; cout << "16진법 : " << nNum << endl; //10진법 다른 방법 dec(cout); cout << "10진법 : " << nNum << endl; //8진법 다른 방법 oct(cout); cout << "08진법 : " << nNum << endl; //16진법 다른 방법 hex(cout); cout << "16진법 : " << nNum << endl; return 0; }
※부동 소수점의 출력 정밀도 설정
정밀도를 설정할 때는 cout의 멤버 함수인 precision을 이용하여 설정한다.
정밀도는 출력 모드에 따라 그 의미가 조금씩 다르다.
글과 아래 표만 봐서는 이해가 잘 안되는데, 예제를 실행시켜보면 이해가 될 것이다.
출력 모드 |
정밀도 의미 |
디폴트 모드 |
총 자릿수 |
고정 소수점 표기 모드 |
소수점 아래 자릿수 |
지수 표기 모드 |
소수점 아래 자릿수 |
#include <iostream> using namespace std; int main( ) { float fValue1( 20.04 ); float fValue2 = 3.141592; //디폴트 모드 cout << "fValue1 : " << fValue1 << endl; cout << "fValue2 : " << fValue2 << endl; //고정 소수점 표기 모드 cout << fixed; cout.precision( 4 ); cout << "fValue1 : " << fValue1 << endl; cout << "fValue2 : " << fValue2 << endl; //지수 표기 모드 cout << scientific; cout.precision( 6 ); cout << "fValue1 : " << fValue1 << endl; cout << "fValue2 : " << fValue2 << endl; //디폴트 모드 cout << defaultfloat; cout.precision( 5 ); cout << "fValue1 : " << fValue1 << endl; cout << "fValue2 : " << fValue2 << endl; return 0; }
[C++] 05. 인라인 함수 - inline function (1) | 2014.01.23 |
---|---|
[C++] 04. 매개변수의 디폴트 값 (0) | 2014.01.22 |
[C++] 03. 함수 오버로딩 ( function overloading ) (0) | 2014.01.22 |
[C++] 02-02. scanf를 대신하는 cin (0) | 2014.01.22 |
[C++] 01. Hello World (0) | 2014.01.21 |
※C++요약
이 게시글에서는 C++의 가장 기본이 되는 구조를 전반적으로 간단히 살펴본다.
※C++특징
- C++은 1980년대 초 Bjarne Stroustrup에 의해 개발되었다.
- C++ 표준을 정하기 위해 ANSI와 ISO가 1년에 세 번 소집된다.
- ANSI/ISO 위원회를 통해 RTTI, Template, STL 등의 새로운 특성이 C++에 추가 되었고 지금도 추가되고 있다.
- dll(동적)이나 lib(정적) 라이브러리를 제외한 C++프로그램은 반드시 main( )가 있어야 한다.
- C++의 OOP 특성은 고수준의 추상화를 제공한다.
- C++의 C 특성은 저수준의 하드웨어 접근을 제공한다.
※예제
#include <iostream> //전처리 지시자 using namespace std; //정의 가시화 int main( ) //함수 머리 { //함수 몸체의 시작 cout << "Hello World"; //메시지 출력 cout << endl ; //새로운 행 시작 return 0; //main 함수를 종료 } //함수 몸체의 끝
[C++] 05. 인라인 함수 - inline function (1) | 2014.01.23 |
---|---|
[C++] 04. 매개변수의 디폴트 값 (0) | 2014.01.22 |
[C++] 03. 함수 오버로딩 ( function overloading ) (0) | 2014.01.22 |
[C++] 02-02. scanf를 대신하는 cin (0) | 2014.01.22 |
[C++] 02-01. printf를 대신하는 cout (0) | 2014.01.21 |
※요약
당연한 얘기겠지만 비트 연산자는 비트를 연산하기 위한 연산자입니다.
비트란( bit )란 기억 장치의 최소 단위로써 1이나 0을 저장하며 8개가 모여 1Byte를 이룹니다.
비트 연산은 정수나 정수로 변환 가능한 타입만 가능하며, 실수나 포인터 등은 비트 연산을 할 수 없습니다.
아래는 8bit( 1Byte )공간에 10진수로는 89, 16진수로는 0x59가 저장되어 있는 모양입니다.
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
64 + 16 + 8 + 1 = 89 입니다.
※비트 연산자 표
연산자 |
피연산자 개수 |
설명 |
~ (NOT) |
1개, 단항 |
비트를 반전 시킨다. |
& (AND) |
2개, 이항 |
두 개의 비트가 모두 1일 때 1 |
| (OR) |
2개, 이항 |
두 개의 비트 중 1개만 1이어도 1 |
^ (XOR) |
2개, 이항 |
두 개의 비트가 같으면 0, 다르면 1 |
<< |
2개, 이항 |
지정한 수만큼 왼쪽으로 비트들을 이동 |
>> |
2개, 이항 |
지정한 수만큼 오른쪽으로 비트들을 이동 |
마스크 오프 : 특정 비트를 강제로 0으로 만드는 연산을 mask off라고 하며 &연산자가 쓰인다.
마스크 온 : 특정 비트를 강제로 1로 만드는 연산을 mask on이라고 하며 |연산자가 쓰인다.
마스크 반전 : 반전시키고자 하는 부분만 반전 시키는 연산을 마스크 반전이라 하며 ^연산자가 쓰인다.
※비트 연산자 진리표
b1 |
b2 |
b1 & b2 |
b1 | b2 |
b1 ^ b2 |
~b1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
※쉬프트 연산자 <<, >>
0 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
상기의 0101 1001을 a라고 하고 쉬프트 연산을 통해 좌측으로 2칸 옮겨 보겠습니다.
a << 2
0 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
<<2
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
보시다시피 좌측으로 2칸 이동하였습니다.
이 때 좌측 두 칸은 버리고, 오른쪽 두 칸은 0으로 채웁니다.
※예제
#include <stdio.h> int main( ) { int nNum1 = 3; int nNum2 = 5; int nResult = 0; nResult = nNum1 & nNum2; printf( "%d & %d 연산 : %d\n", nNum1, nNum2, nResult ); nResult = nNum1 | nNum2; printf( "%d | %d 연산 : %d\n", nNum1, nNum2, nResult ); nResult = nNum1 ^ nNum2; printf( "%d ^ %d 연산 : %d\n", nNum1, nNum2, nResult ); nResult = ~nNum1; printf( "%d ~ %d 연산 : %d\n", nNum1, nNum2, nResult ); nResult = nNum1 << 2; printf( "%d << %d 연산 : %d\n", nNum1, 2, nResult ); nResult = nNum1 >> 2; printf( "%d >> %d 연산 : %d\n", nNum1, 2, nResult ); return 0; }