[포스코x코딩온] 스마트팩토리 1주차 회고 | C++ 기초 문법

이남웅·2023년 3월 26일
0

벌써 스마트팩토리 1주차가 오늘부로 끝나간다. 1주차에는 전에 올린 기본적인 github와 기초문법 C++를 배웠다. C++은 C언어와 기본적인 형태는 같지만 문자열을 선언하거나, 문자를 출력, 입력할 때 문법이 다르다. C언어는 문자열을 사용하기 위해서는 배열을 사용해야 하는데 C++는 문자열을 사용할 때 배열을 사용하지 않아도 되어서, C언어 이후로 나온 python 같이 사용하기가 편한 것 같다. 이 글에서는 C언어에 없는 기능 중점으로 작성하였다.

1. C++에 대한 기초 지식

C언어의 라이브러리는 stdio.h 라이브러리를 사용한다. 반면 C++ iostream이라는 라이브러리를 사용한다. C언어와 마찬가지로 임베디드나 서버 구축 등 활용범위가 넓다. C++의 특징이라면 객체 지향 개념을 사용하여 절차 지향인 C언어에 비해서 효율성 저하를 최소화하였다.
이게 무슨말이냐면 절차 지향은 말 그대로 절차대로 위에서 아래로 순차적으로 처리를 한다. 이러한 방식은 컴퓨터 처리 방식과 같기 때문에 속도가 빠르다. 경험담으로 졸업작품을 라즈베리파이에서 파이썬으로 만들었는데 C언어로 동작되는 아두이노보다 처리속도가 느려 최적화하는데 정말 많이 애를 먹었다. 대신 유지보수가 어렵고, 코드 순서가 변경되면 결과가 달라질 수 있다.
객체 지향은 데이터와 절차를 하나의 덩어리 즉, 객체 단위로 처리를 하게 된다. 캡슐화라고 하며 절차 지향보다 데이터 단위가 크기 때문에 속도가 느리다.

2. 동적 배열

c++에서는 변수를 입력 받아 변수만큼의 배열을 선언하려고 한다면 일반적인 배열을 사용하여 선언하면 컴파일러 오류가 뜨는 것을 알 수 있다. 이러한 경우 동적 배열이나 vector를 사용하여 배열을 선언하여야 한다.
C++에서 배열을 선언할 때에는 크기를 정하고 배열을 선언할 수 있다. 이러한 배열을 정적 배열이라 하며 정적 메모리인 STACK 영역에 저장되어 크기가 정해져야 한다. 반면 동적 배열은 동적 메모리인 HEAP 영역에 저장되어 할당과 해제를 수동적으로 해주어야 하지만 자유롭게 할당과 해제를 할 수 있다.

int *arr = new int [num]; 	//동적 배열 할당
delete [] arr;				//동적 배열 해제

동적 배열 할당을 보게 되면 정수형 arr의 동적 배열을 선언하게 되는데 그 크기는 num의 크기로 만들어진다. 동적 배열 할당을 할 때에는 포인트 변수를 사용하게 되며 포인트 변수는 변수의 주소값을 저장한다. 동적 배열을 사용한 후에는 까먹지 않고 동적 배열 해제를 해주어야 한다.

배열인 만큼 다차원 배열을 사용할 수 있다. 2차원 동적 배열을 만들게 되면 다중포인터를 사용하여 동적 배열 할당을 하게 된다.

int ** arr = new int *[x]	//동적 배열 할당

for (int i = 0; i < y; i++)
	arr[i] = new int [x]
    
for (int i = 0; i < x; i++)	//동적 배열 해제
	delete[] arr[i];
   
delete[] arr;

2차원 동적 배열을 할 때에는 반복문을 사용하여 만들고자 하는 num의 크기만큼 동적 배열 할당을 해야 한다. x, y축으로 설명하게 되면 이중포인터를 사용하여 x축의 배열을 만들게 되고, x축의 안의 y축을 만들기 위해 반복문을 통해서 x축 만큼 반복하여 y축쪽의 배열을 할당해준다. 동적 배열 해제를 할 때에는 x축 크기만큼의 반복문을 사용하여 해제를 진행하고 최종적으로 배열까지 해제를 해주면 된다.

3. vector

vector는 동적 배열에 반해 자동으로 메모리를 할당해주는 배열이다. 포인터를 사용하지 않아도 크기를 추후에 지정이 가능하고 중간에 크기를 바꾸는 것도 가능하다. 그 외 여려 명령어도 추가적으로 사용하여 배열을 수정하는 것도 가능하다.

std::vector<int> v = {1, 2, 3, 4, 5};	//5개의 배열을 선언하여 각각의 숫자로 초기화
std::vector<int> v(5);					//5개의 배열을 선언
std::vector<int> v(5, 0);				//5개의 배열을 선언하고 0으로 초기화

vector를 이용하여 변수만큼의 배열을 선언하고자 하면 다음과 같이 해주면 된다.

int num = 0;
std:cin >> num;
std::vector<int> v(num, 0)

여기 중요한 점은 vector에 값을 대입하기 전에 초기화를 꼭 해주어야 한다. 초기화를 하지 않으면 세그먼트 오류가 발생하므로 vector를 선언할 때 초기화도 같이 진행해주자.

다음은 명령어를 통해 vector를 다룰 수 있는 추가적인 명령어이다.

.at("인덱스")				    //인덱스에 해당하는 값을 반환
.front()					//vector의 첫번째 요소를 반환
.back()						//vector의 마지막 요소를 반환
.size()						//vector의 길이를 반환
.push_back("원소")		    //vector의 제일 마지막에 원소를 삽입
.pop_back()					//vector의 제일 마지막 부분 제거
.begin()					//vector의 첫번째 요소의 주소값 반환
.insert(v.begin() + 2, "원소")	 //2번 인덱스에 원소를 삽입
.erase("시작 주소값", "끝 주소값")	 //시작 주소값부터 끝 주소값까지의 요소를 삭제
.clear()						 //vector의 모든 요소를 삭제

4. namespace

namespace는 프로그래밍을 하면서 변수나 함수 등의 이름이 같아져 충돌이 일어날 확률을 줄여주기 위한 기능이다.

namespace class_1
{
	std::string name
}

namespace class_2
{
	std::string name
}

int main(void)
{
	std::cout << 1반 << class_1::name;
    std::cout << 2반 << class_2::name;
}

코드를 확인해보면 1반의 이름과 2반의 이름이 namespace로 나누어져있다. 이런 경우 2차 배열을 통해서 나눌 수 있지만 namespace를 통해서 class_ ::name을 통해서 불러올 수 있다. 유심히 보다보면 C++를 사용하면서 입출력할 때 사용하는 std::cout과 std::cin도 namespace로 구성되어있다는 것을 알 수 있다. 여기서 만약 namespace를 생략하고 싶다면, main함수 위에

using namesapce "함수명"

을 써주어 변수명 그대로 name을 사용하게 되면 using namespace를 한 함수의 변수를 그대로 사용할 수 있다.

Python이나 C언어를 바탕으로 만들어진 C++를 공부하면서 크게 보면 개발언어들의 형태는 크게 다르지 않다는 것이 많이 느껴진다. 많은 개발 언어들이 C언어에 영감을 받아 개발되어지고 있으며 점점 갈수록 그 중요도는 계속해서 높아질 것으로 생각이 든다. 애플이 만든 swift나, 최근에 뜨고 있는 Ruby 등 새롭게 나오는 언어를 배우기 전 C언어를 확실하게 공부하고 넘어가야 다른 개발 언어를 공부하게 될 때 더 많은 도움이 될 것으로 생각이 든다.

0개의 댓글