학습 개요
- 흐름 제어 구문, 구조체 및 클래스, 배열과 포인터, 동적 메모리 할당, 참조 등 C++ 프로그램의 기본적인 구문에 대하여 소개함
- 클래스 선언문에 대해서 C언어의 구조체와 비교하는 수준에서 학습함
- 포인터 및 동적 메모리 할당에 대한 내용은 이해가 쉽지 않으며, 문법적으로는 잘 이해하고 있다 해도 실제 활용 과정에서 에러를 유발하기 쉬우므로 많은 실습을 통해 깊이 있는 학습을 하는 것이 필요함
학습 목표
- 흐름 제어 구문을 이용하여 구현하고자 하는 논리에 맞게 문장의 흐름 제어를 할 수 있음
- 구조체와 클래스의 차이점을 설명할 수 있음
- 배열을 이용하여 여러 개의 데이터 집합에 대해 반복적 처리를 할 수 있음
- 메모리를 필요한 시기에 필요한 만큼 동적으로 할당하거나 반환할 수 있음
- 동적으로 할당된 메모리 공간을 포인터를 이용하여 액세스할 수 있음
- l-value 참조를 활용할 수 있음
주요 용어
- 구조체
- 여러 가지 자료형의 데이터 집합을 저장할 수 있는 새로운 자료형을 정의한 것
- 클래스(class)
- 객체 지향 프로그래밍에서 표현하고자 하는 대상(객체)의 데이터(속성)와 함께 그 대상이 할 수 있는 동작을 나타내는 함수(행위)들을 묶어서 선언한 것
- 배열(array)
- 동일한 자료형의 값을 여러 개 저장할 수 있는 연속적으로 할당된 공간을 묶어 하나의 이름을 갖는 변수로 만든 것
- 포인터(pointer)
- 어떠한 대상이 위치한 곳을 가리키는(주소를 저장하는) 변수
- 동적 메모리 할당
- 프로그램 동작 중에 기억 공간의 필요성 및 소요 량을 결정하여 필요한 공간을 할당하는 것
- 참조(reference)
- 프로그램에서 어떤 데이터를 간접적으로 액세스할 수 있도록 그 데이터를 가리키는 값(주소)
강의록
흐름 제어 구문
기본적인 흐름 제어 구조
- 순차 구조
- 문장이 나열 된 순서에 따라 차례로 실행하는 구조
- 조건 제어 구조
- 지정 된 조건에 따라 실행 흐름을 제어하는 구조
if
문,switch
문
- 반복 제어 구조
- 정해진 범위의 문장을 반복적으로 실행하게 하는 구조
for
문,while
문,do while
문
조건문 - if
if
문 사용 형식1 2 3 4
if (조건) 문장1; // 조건이 참일 때 실행할 문장 else 문장2; // 조건이 거짓일 때 실행할 문장
ex) 변수 a와 b에 저장 된 값 중 큰 값을 출력하기
1 2 3 4
if (a > b) cout << a << endl; else cout << b << endl;
조건문 - switch
switch
문 사용 형식1 2 3 4 5 6 7 8 9 10
switch (정수형_수식) { case 값1 : 문장1; // 정수형_수식 == 값1 일 때 실행할 문장들 나열 break; // switch문을 빠져 나가게 함 case 값2 : 문장2; // 정수형_수식 == 값2 일 때 실행할 문장들 나열 break; // switch문을 빠져 나가게 함 default: // 정수형_수식의 값과 일치하는 case 값이 없을 때 문장n; // 실행할 문장들을 나열 }
switch
문 사용 예ex) int형 변수 score의 값에 따라 A ~ F의 학점 부여하기
1 2 3 4 5 6 7 8 9 10 11 12
switch (score / 10) { case 10: // score가 100인 경우 case 9: grade = 'A'; // score가 90~99인 경우 break; case 8: grade = 'B'; // score가 80~89인 경우 break; case 7: grade = 'C'; // score가 70~79인 경우 break; case 6: grade = 'D'; // score가 60~69인 경우 break; default: grade = 'F'; // score가 59 이하인 경우 }
반복문 - for
문 루프
for
문 사용 형식1 2
for ( 초기화_문장 ; 반복조건 ; 증감_문장 ) 반복할_문장;
ex) 10개의 정수 값을 입력하여 합계 구하기
1 2 3 4 5 6
int val, total = 0; for (int i = 0 ; i < 10 ; i++) { cin >> val; total += val; }
범위 기반
for
루프1 2
for (원소선언 : 데이터집합) 반복할_문장;
ex) 배열 안의 모든 값을 합산 하기
1 2 3 4 5 6 7
int arr[5] = {2, 3, 9, 4, 7}; int sum = 0; for (int a : arr) sum += a; cout << "합계 = " << sum << endl;
반복문 - while
루프
while
문 사용 형식1 2
while (반복조건) 반복할_문장;
ex)
for
루프를while
루프로 표현 하기1 2 3 4 5 6
int val, total = 0; for (int i = 0 ; i < 10 ; i++) { cin >> val; total += val; }
1 2 3 4 5 6 7 8 9
int val, total = 0; { int i=0; while (i < 10) { cin >> val; total += val; i++; } }
반복문 - do
~ while
루프
do
~while
문 사용 형식1 2 3
do 반복할_문장; while (반복조건 );
구조체와 클래스
구조체
- 구조체
- 여러 가지 자료형 데이터 집합을 저장할 수 있는 새로운 자료형을 정의한 것
구조체 선언문 형식
1 2 3 4
struct StructName { Type1 item1; Type2 item2; };
- 구조체의 예
2차원 좌표
1 2 3
struct C2dType { double x, y; };
원
1 2 3 4
struct CircleType { C2dType center; double radius; };
- 구조체 데이터를 처리하는 함수
- C 언어에서는 구조체와는 별개의 함수로 정의함
ex) 원의 면적 구하기
1 2 3 4
double circleArea(CircleType c) { return c.radius * c.radius * PI; }
1 2 3 4
int main() { CircleType c1 = { {0, 0}, 10}; cout << " 원의 면적 : " << circleArea(c1) << endl; }
클래스
- 클래스
- 표현하고자 하는 대상(객체)의 데이터(속성)와 함께 그 대상이 할 수 있는 동작을 나타내는 함수(행위)들을 묶어서 선언한 것
ex) 원 클래스
행위 init
: 원의 초기화area
: 원의 면적을 계산chkOverlap
: 다른 원과 중첩 여부 검사display
: 원의 정보 디스플레이속성 center
: 중심 좌표radius
: 반경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
class CircleClass { // 원 클래스 C2dType center; // 중심 좌표 double radius; // 반경 public: // 중심 (cx, cy), 반경 r로 원을 초기화 void init(double cx, double cy, double r) { center.x = cx; center.y = cy; radius = r; } // 원의 면적 계산 double area() const { return radius * radius * PI; } bool chkOverlap(const CircleClass& c) const { double dx = center.x - c.center.x; double dy = center.y - c.center.y; double dCntr = sqrt(dx*dx + dy*dy); return dCntr < radius + c.radius; } void display() const { } };
1 2 3 4 5 6 7 8 9 10 11 12 13
int main() { CircleClass c1, c2; c1.init(0, 0, 10); // 중심(0, 0), 반경 10으로 초기화 c2.init(30, 10, 5); // 중심(30, 10), 반경 5로 초기화 cout << "원1" << endl; c1.display(); cout << " 원1의 면적 : " << c1.area() << endl; cout << "원2" << endl; c2.display(); cout << " 원2의 면적 : " << c2.area() << endl << endl; }
구조체와 클래스의 비교
배열
배열
- 동일한 자료형의 값을 여러 개 저장할 수 있는 연속적으로 할당 된 공간을 묶어 하나의 이름을 갖는 변수로 만든 것
- 각각의 원소는 0번부터 시작하여 차례로 부여 된 번호(첨자, 인덱스)를 이용하여 액세스 함
- 배열의 차원
- 배열의 첨자 개수
1차원 배열
1차원 배열의 선언
1차원 배열의 사용
1 2 3 4 5
float fArray[4]; int i = 0; fArray[i] = 10.0f; cin >> fArray[1] >> fArray[2] >> fArray[3]; cout << fArray[1] * fArray[2];
다차원 배열
- 2차원 배열
1차원 배열이 원소인 배열
1
int Arr2D[4][3];
배열의 활용
배열의 초기화
1 2 3 4
int a[5] = { 1, 2, 3, 4, 5 }; // '='는 생략할 수 있음 int b[5] = { 1, 2, 3 }; // b[3]와 b[4]는 0으로 초기화됨 int c[] = { 1, 2, 3, 4, 5 }; // 배열의 크기는 5임 int d[2][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }; // 2차원 배열의 초기화
여러 개의 데이터 중 최댓 값 구하기
MaxValue.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int main() { int max; int data[10] = { 10, 23, 5, 9, 22, 48, 12, 10, 55, 31 }; max = data[0]; // data의 0번 값을 max로 가정함 cout << "데이터 : " << data[0]; // 0번 데이터 출력 for (int i = 1; i < 10; i++) { // 나머지 9개의 데이터 비교 cout << " " << data[i]; // i번 데이터 출력 if (max < data[i]) max = data[i]; // i번 데이터 비교 } cout << "\n\n배열의 최댓값 : " << max << endl; return 0; }
포인터와 동적 메모리 할당
포인터의 활용
- 포인터
- 어떠한 대상이 위치한 곳을 가리키는(주소를 저장하는) 변수
- 가리키는 대상
- 포인터에 지정 된 자료형에 해당 되는 변수, 동적으로 할당 된 메모리, 함수 등
- 가리키는 대상
- 어떠한 대상이 위치한 곳을 가리키는(주소를 저장하는) 변수
포인터 선언 형식
1
TypeName* ptrVar;
TypeName
- 가리킬 값의 자료형
ptrVar
- 포인터 변수의 이름
1
int* iPtr;
- 포인터의 사용
포인터가 유효한 대상을 가리키게 한 후 사용해야 함
1 2
ptrVar = &var; // ptrVar이 var을 가리키게 함 *ptrVar = value; // ptrVar을 이용하여 var을 액세스
&
- 주소 계산 연산자
*ptrVar
- 포인터 ptrVar가 가리키는 곳
1 2 3
int a; int* iPtr = &a; *iPtr = 10;
- 포인터의 사용 예
SimplePt.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <iostream> using namespace std; int main() { int a = 10; int* ptr; ptr = &a; // ptr에 a의 주소를 넣는다. cout << "ptr이 가리키는 값 : " << *ptr << endl; // 출력되는 값 : 10 *ptr = 20; cout << "변수 a의 값 : " << a << endl; // 출력되는 값 : 20 return 0; }
동적 메모리 할당
- 동적 메모리 할당이란?
- 프로그램 동작 중에 기억 공간의 필요성 및 소요 량을 결정하여 필요한 공간을 할당하는 것
- 기억 공간의 생성 시점
new
연산자의 실행 시점
- 기억 공간의 소멸 시점
delete
연산자의 실행 시점
- 기억 공간의 생성 시점
- 포인터 변수가 할당 된 기억 공간을 가리키게 함
- 프로그램 동작 중에 기억 공간의 필요성 및 소요 량을 결정하여 필요한 공간을 할당하는 것
메모리 할당 연산자
1
ptrVar = new TypeName;
1
ptrVar = new TypeName[n];
메모리 반납 연산자
1
delete ptrVar;
1
delete [] ptrVar;
단일 데이터 공간의 할당 및 반환
1 2 3
int* intPtr; intPtr = new int; *intPtr = 10;
1 2 3 4 5 6
int* intPtr; intPtr = new int; *intPtr = 10; delete intPtr; intPtr = nullptr; // 아무 것도 가리키지 않는 포인터
배열 데이터 공간의 할당 및 반환
1 2 3 4 5
int* intPtr; intPtr = new int[4]; *intPtr = 10; *(intPtr+1) = 20; intPtr[2] = 30;
1 2 3 4 5 6 7 8
int* intPtr; intPtr = new int[4]; *intPtr = 10; *(intPtr+1) = 20; intPtr[2] = 30; delete [] intPtr; intPtr = nullptr;
참조
l-value 참조
- 참조(reference)
- 어떠한 대상을 가리키는 값
- 포인터와 유사함
- 참조 변수는 참조 대상의 별명처럼 사용할 수 있음
- I-value 참조
- 실체가 있는 대상(I-value)에 대한 참조
- 어떠한 대상을 가리키는 값
l-value 참조 변수의 선언 형식
1
TypeName& refVar = varName;
TypeName
- 참조 대상의 자료형
refVar
- 참조 변수의 이름
varName
- 참조 대상
l-value 참조 변수의 사용 예
const
참조참조 변수가 참조하는 대상의 값을 바꿀 수 없음
1 2 3 4
int x { 10 }; const int& xRef = x; cout << xRef << endl; // x의 값을 읽어 출력함 xRef += 10; // 오류: const 참조로 값을 수정할 수 없음
- 참조가 포인터와 다른 점
- 참조 변수를 이용하여 값을 읽거나 저장할 때 참조 대상 변수를 사용하는 형식과 동일함
- 참조 변수는 초기화를 통해 반드시 어떤 대상을 참조해야 함
- 초기화 되지 않은 상태로 인해 무엇을 참조하고 있는지 알 수 없는 상황은 발생하지 않음
- 참조 변수는 초기화를 통해 지정 된 참조 대상을 바꿀 수 없어 참조의 유효 기간 동안 하나의 대상만 참조할 수 있음
r-value 참조
- r-value 참조
- 사용한 후에는 그 값을 더 이상 가지고 있을 필요가 없는 대상을 참조
- r-value 참조의 용도
- 객체의 값을 다른 객체로 이동
연습 문제
위 지문에서 배열의 항목에 cin으로 부터 입력된 값을 넣으려고 한다. 공란에 넣을 내용은?
1 2 3 4
int arr[10]; for ( // _______ : arr) cin >> a;
a.
int& a
- 범위 기반
for
루프에서 arr의 각 원소를 나타내는 선수를 선언함 - 이때 arr의 값을 입력을 통해 변경해야 하므로 참조형으로 선언함
- 범위 기반
C++ 에서 클래스와 구조체의 차이점을 바르게 설명한 것은?
a. 클래스의 항목들은 공개 여부를 지정하지 않은 경우 공개되지 않는 것이 기본이나, 구조체의 항목들은 공개되는 것이 기본이다.
- 구조체는 내부 데이터 항목들을 외부에서 자유롭게 사용하도록 공개하는 것이 디폴트임
- 클래스의 경우는 내부의 구현을 감추는 것이 디폴트임
10개의 int형 값을 저장하는 공간을 동적 할당하는 명령을 바르게 사용한 것은?
a.
int *iPtr = new int[10];
- new 명령으로 할당 받을 자료형 이름을 쓰고 그 뒤에 [크기]의 형식으로 할당 크기를 지정함
위 지문에서 int형 포인터 iPtr의 선언이 올바르게 사용된 것은?
a.
1 2
int a; int *iPtr = &a;
- 포인터는 동일한 자료형의 데이터를 가리키도록 해야 함
- 어떠한 변수를 가리키도록 하려면 변수의 주소를 계산하는
&
연산자를 사용함
다음 중 l-value 참조 ref를 선언하는 문장으로 올바른 것은? 단, a는 int형 변수이다.
a.
int& ref = a;
- l-value 참조는 & 기호를 이용하여 선언함
- 이때 참조 대상을 지정하여 초기화해야 함
- l-value 참조의 대상은 l-value여야 하며, 참조 대상과 자료형이 같아야 함
auto& ref = 10;
에서는 참조 대상이 int형 리터럴이므로const
참조로 선언해야 참조할 수 있음
정리 하기
if
문 및switch
문을 이용하여 조건 제어 구조를 만들 수 있으며,for
,while
,do while
문을 이용하여 반복 제어 구조를 작성할 수 있음- 클래스를 이용하여 표현 대상이 어떤 일을 할 수 있는가(행위)와 이를 위해 어떤 데이터를 저장하는가(속성)를 선언함
- 배열을 이용하여 동일한 자료형의 값을 여러 개 연속적 저장 공간에 저장하고 첨자를 지정하여 개별 원소를 액세스할 수 있는 변수를 만들 수 있음
- 포인터를 이용하여 값이 저장되어 있는 곳이나 함수를 가리키게 하여 간접적으로 액세스할 수 있음
new
연산자를 이용하여 메모리를 동적으로 할당하여 사용할 수 있으며,delete
연산자를 이용하여 사용이 끝난 메모리를 반납할 수 있음- 참조형 변수를 이용하여 변수 등을 참조할 수 있으며, 초기화에 의해 지정된 참조 대상을 교체할 수 없음