메모장
열혈 C++ 복습 2 본문
♨ 개인적 해석이 다분한 글임으로, 인지하지 못한 오류가 있을 수 있습니다 ♨
교재 - <윤성우 열혈 C++ 프로그래밍>
▣ C언어 용어/개념 복습
- const 키워드 : 변수를 상수화 / 상수화된 변수는 저장된 값을 변경할 수 없다
- 실행중인 프로그램의 메모리 공간 : 데이터/스택/힙
데이터 : 전역변수가 저장되는 공간
스 택 : 지역변수 및 매개변수가 저장되는 영역
힙 : malloc 함수호출에 의해 프로그램이 실행되는 과정에서 동적으로 할당되는 영역
-> malloc과 free : malloc은 동적으로 메모리 할당 / free는 할당된 영역 해제
▣ 새로운 자료형 bool
- ture / false : 얘네로 그냥 참/거짓 표현 가능 ( 기본적으로 0을 거짓, 나머지 정수를 참을 의미)
- bool변수의 크기는 1byte
▣ 참조자(Reference)의 이해
- 변수 = 할당된 메모리에 붙여진 이름 ∴ 변수를 통해서 해당 메모리에 접근 가능
- " & " 를 이용하여 이미 할당한 변수 이외의 다른 이름을 해당 메모리에 붙일 수 있다
예)
-> 변수(num1)와 참조자(num2) 모두 같은 공간을 의미하기 때문에 참조자를 이용해서 값을 변경할 수 있다
∴ 참조자 = 자신이 참조하는 변수를 대신할 수 있는 다른 이름
- 대신 참조자는 변수를 대상으로만 선언이 가능하다, 선언 후에는 변수와 같은 역할을 수행할 수 있다
(지역/전역의 구분도 동일하게 적용된다)
- 참조자 수에는 제한이 없다 -> 한 개의 변수에 여러개의 참조자를 붙일 수 있다
- 참조자를 대상으로한 참조자를 선언할 수도 있다. 그러나 참조자는 선언과 동시에 변수를 참조해야만 한다
-> int &ref = 20; (X) : 변수가 아닌 상수를 참조할 수 없다
int &ref; (X) : 선언만하고 참조를 나중에할 수 없다
int &ref = NULL (X) : NULL값도 안된다
int &ref = arr[3] (O) : 배열요소는 변수로 간주되어 참조 가능하다
▣ 참조자(레퍼런스)와 함수
- Call-by-value 와 Call-by-reference
-> Call-by-value : 값을 인자로 전달하는 함수의 호출방식
Call-by-reference : 주소 값을 인자로 전달하는 함수의 호출방식
- 여기서 reference가 그 레퍼런스
예)
-> 주소 값이 외부 변수의 "참조"도구로 사용되는 함수의 호출
주소를 인자로 받는다? -> 아른모직다
주소를 받아 참조도구로 사용한다 -> Call-by-reference
- 함수 외부에 선언된 변수의 접근 방법
1. 주소 값을 이용한다
2. 레퍼런스(참조자)를 이용한다
- 참조자를 이용한 Call-by-reference
예)
->매개변수에 있는 두 참조자의 선언은 사실 인자로 받은 변수들로 각각을 초기화하겠다는 뜻
(실제로 SwapByRef(val1, val2)가 실행되면 int &ref1 = val1, int &ref2 = val2 로 실행된다)
- 참조자를 이용한 Call-by-reference의 단점
-> 위와 같이 참조자를 이용한 Call-by-reference함수가 있다면 호출부만 보고서 판단하기 어려워 진다
즉, 해당 함수의 원형을 확인해야 하고, 매개변수에 참조자가 선언되었다면
함수의 정의부까지 가서 확인해봐야 한다
- 이에 대한 대안으로 함수 선언부 매개변수에 const를 두어 함수 선언부만 보고 값이 변경되지 않다는 것을 보여준다
예) void NoSwap(const int &num); -> 참조자 num에 의해서 값이 변경되지 않는다
- 반환형이 참조형(Reference Type)인 경우
예)
-> 순서대로 파악해보면
1) num1을 1로 초기화 한다
2) RefRetFuncOne함수를 이용해 num1의 주소에 있는 값(1)에 +1을 한 후
그 값을 레퍼런스 num2에 초기화한다
(∴ num1의 주소 = num2의 주소)
3) num1++
4) num2++ (num1의 주소에 있는 값++ = num1++)
5) 그래서 num1과 num2의 출력값은 동일하다
=> 결정적으로 int형 변수는 단 1개이고 나머지는 레퍼런스, 매개변수에 선언된 레퍼런스 임으로
결국 1개의 4byte 메모리 공간에 대해서만 작업한 것
또 다른 예)
-> 이번에도 순서대로 파악해보면
1) num1을 1로 초기화 한다
2) 이전과 동일한 RefRetFuncOne함수를 이용해 num1의 주소에 있는 값(1)에 +1을 한 후
그 값으로 변수 num2를 초기화한다
(∴ num1의 주소 ≠ num2의 주소 / 이때의 num1 = 2, num2 = 2)
3) num1++ // num1 = 3
4) num2 + 100 // num2= 102
=> RefRetFuncOne은 동일하게 사용되었으나 반환된 레퍼런스가
변수에 저장되는가 레퍼런스에 되는가에 따라 차이가 생겼다
- 잘못된 참조의 반환
-> 위 함수에서 함수 내 지역변수인 num을 참조형으로 반환하고 있다
그러나 이 함수가 반환되면 지역변수 num은 소멸한다
∴ 이 함수를 통해 참조자를 초기화 했다면 오류가 생긴다
(찌끄래기 값을 참조하게된다 = 원하는 결과를 절대 얻을 수 없다)
- const 참조자의 또 다른 특징
const가 붙은(상수화된) 변수에 대한 레퍼런스를 선언하기 위해선 레퍼런스에도 const를 붙여야 한다
예) const int num = 20;
int& ref = num; (X)
const int& ref2 = num; (O)
또한 const를 이용하여 '상수'도 참조할 수 있다
-> int num = 20 + 30;
위 문장에서 20과 30은 리터럴 (상수) (literal constant)라 한다
리터럴 상수는 해당 행에서만 존재하고 다음 행으로 넘어가면 존재하지 않는다
이때 const를 이용하여 리터럴 상수를 레퍼런스로 참조할 수 있다
예) const int &ref = 30;
리터럴 상수 30에 대한 임시 변수를 만들고 const 레퍼런스가 그 임시변수를 참조하게 된다
활용법
-> "위 같이 정의된 함수에 인자의 전달을 목적으로 변수를 선언한다는 것은 매우 번거로운 일이다
그러나 임시변수를 통한 const 레퍼런스의 상수 참조를 허용함으로써, 매우 간단히 호출이 가능해졌다"
고 책에 적혀 있다
=> 킹직히 좀 헷갈린다;
인자로 상수를 주고 그것을 위한 변수를 따로 설정하지 않고 임시변수 정도만 만들고 실행가능하다는 말인가?
아니면 호출 시에 상수를 그냥 넣을 수 있다는 말인가?
추후에 다시 와서 정리해야지
▣ malloc & free -> new & delete
- malloc/free 복습
예) 1. 길이 정보를 인자로 받아서, 2. 해당 길이의 문자열 저장이 가능한 배열을 생성하고,
3. 그 배열의 주소 값을 반환하는 함수
-> 여기서 보이는 malloc의 단점
1. 할당할 대상의 정보를 무조건 바이트 크기단위로 전달해야 한다
2. 반환형이 void형 포인터 이기 때문에 적절한 형 변환을 거쳐야 한다
=> 이를 보안하기위해 나온 new 키워드!!
-> int형 변수의 할당 : int * ptr1 = new int;
double형 변수의 할당 : double * ptr2 = new double;
길이가 3인 int형 배열의 할당 : int * arr1 = new int[3];
길이가 7인 double형 배열의 할당 : double * arr2 = new double[7];
- 객체의 생성에는 반드시 new & delete
-> 이것도 잘 모르겠으나 아무튼 malloc과 new간에는 작동방식에 차이가 있다는 것은 확실하다
- 힙에 할당된 변수를 포인터를 사용하지 않고 접근하는 방법
-> 레퍼런스!
예)
-> 레퍼런스의 선언을 통해서 포인터 연산 없이 힙 영역에 접근 가능
▣ C++에서 C언어의 표준함수 호출하기
- C++에서 C언어 표준함수를 사용하기 위해 기존 C언어 헤더파일에서 확장자 .h를 빼고 접두어 c-를 추가하면 된다
예) 이전 코드들에서 보았던 #include<cstdlib>, #include<cstring>등
∴ #include <stdio.h> -> #include <cstdio>
#include <stdlib.h> -> #include <cstdlib>
#include <math.h> -> #include <cmath>
#include <string.h> -> #include <cstring>
연습문제
▣ 2-1 참조자 기반의 Call-by-reference 구현
1. 참조자를 이용해서 다음 요구사항에 부합하는 함수를 각각 정의하고 이를 확인할 수 있는 main함수를 작성하라
- 인자로 전달된 int형 변수의 값을 1씩 증가시키는 함수
- 인자로 전달된 int형 변수의 부호를 바꾸는 함수
2. 아래 코드에서 문제점을 말하시오

3. 다음 코드에 SwapPointer(ptr1, ptr2)라는 함수 호출부를 추가하면 ptr1과 ptr2가 가리키는 대상이
서로 바뀌도록 SwapPoint함수를 정의하라
▣ 2-2 const 포인터와 const 참조자
const int num = 12;
포인터 변수를 선언하여 위 변수를 가리켜라 그리고 이 포인터 변수를 참조하는 참조자를 선언하고
포인터 변수와 참조자를 이용하여 num에 저장된 값을 출력하라
▣ 2-3 구조체에 대한 new & delete 연산
typedef struct __Point
{
int xpos;
int ypos;
} Point;
위의 구조체를 기반으로 두 점의 합을 계산하는 함수를 다음의 형태로 정의하고
(덧셈결과는 함수의 변환을 통해서 얻게 한다)
Point& PntAdder(const Point &p1, const Point &p2);
임의의 두 점을 선언하여, 위 함수를 이용한 덧셈연산을 진행하는 main 함수를 정의하라
단, 구조체 Point 관련 변수의 선언은 무조건 new 연산자를 이용해서 진행해야 하며,
할당된 메모리 공간의 소멸도 필수여야 한다.
(동적할당 및 변수를 함수의 참조형 매개변수의 인자로 어떻게 전달해야 하는가?
함수 내에 선언된 변수를 참조형으로 반환하려면 해당 변수는 어떻게 선언해야 하는가?
이 두 질문에 대한 답을 할 수 있어야 가능한 문제이다)
▣ 2-4 C++ 표준함수 호출
1. 다음 표준함수를 호출하는 예제를 만들되, C++의 헤더(<cstring>)를 선언해서 만들어라
2. rand, srand, time 이 세 함수를 이용해서 0이상 100미만의 난수를 총 5개 생성하는 예제를 만들되
C++의 헤더(time - <ctime> / rand, srand = <cstdlib>)를 선언해서 작성하라
'C++ 복습' 카테고리의 다른 글
열혈 C++ 복습 4 (0) | 2019.11.22 |
---|---|
열혈 C++ 복습 3 (0) | 2019.11.19 |
열혈 C++ 복습 1 (0) | 2019.11.17 |
C++ 복습 1 (0) | 2019.08.04 |