cpp(stl)

cpp3(안전배열/file입출력)

yam3u 2025. 3. 19. 17:28

250313 수업정리본 + 모르는 것..

 

*이건 그냥 내가 자주 까먹는 개념.. 인스터스(instancing)한다.. : 객체를 생성해 메모리를 할당한다.예를 들어.. Dog 라는 클래스를 만들고, dog라는 인스턴스를 만듬.

메모리가 할당되는 시점은.. 인스턴스가 될 때, 객체가 생성이 될 때!

 

virtual : 순수 가상 함수.. 상속과 관련된 개념! 이걸 통해 다형성(polymorphism)을 구현할 수 있음!

다형성 : 같은 이름으로 다른 기능을 하게 하는 것

override : 오버라이딩, virtual이랑 짝이라고 생각하자.. 부모 클래스의 함수를 자식클래스에서 재정의하는 것을 말함.

*

 


랜덤엔진

std::default_random_engine dre{} -> 기본 랜덤엔진 사용. std::random_device{}를 사용할 수 도있지만 이건 매번 다른 값을 불러옴!

std::uniform_int_distribution uid{ 0, 999'9999 }; -> 특정 범위를 설정할 수 있다!

// 엔진의 결과를 특정 분포로 가공해줌.. {0~999'9999}사이의 값을 dre가 랜덤으로 난수를 생성

사용은

int num = uid(dre); 이런식으로 해준다.. 이러면 값이 저 범위 내에서 랜덤으로 들어감~ (난수를 메모리에 저장)


안전배열

std::array 에 관하여.. 우리는 앞으로 STL을 배웠으니 안전배열을 사용하자 ㅎ(std::vector도 존재.. 이건 나중에)

보통 사용법은.. std::array<int, 100> a{};

이런식으로.. array<자료형, 사이즈>라고 생각하면 될듯

std::array는.. 배열의 이름이 *로 자동변환되지 않음..! 원래 int num[100]{}; 이라는 배열이 존재한다고 할 때, numnum [0]이 되기도하며, 배열의 첫번째 주소를 가리키기도 했음..근데 array는 안그런다는 것 같네..또한.. int num[100]; 있을때.. 배열 경계를 벗어나는 문제가 발생할 수 있음.. -> 이걸 std::array 또는 std::vector로 효과적으로 안전하게 배열 관리를 해줄 수 있음

 

array에 관해..

└ at() , out_of_range

int cat[5]는 잘못된 접근.. 얘는 오류여도 저렇게 지렁이만 뜨고 컴파일은 잘 됨..0으로 출력될 뿐

그러나.. dog.at(5)는.. 이렇게 뭐가 잘못됐는지 찝어준다.. 

예외(std::out_of_range)를 던져주는걸 한눈에 확인할 수 있다!!!


array에선 begin, end를 사용할 수 있음..begin -> 배열의 첫번째 인덱스를 가리킴end -> 마지막 인덱스 바로 다음위치를 가리킨다!

이런식으로.. 사용 가능!

begin,end는 sort랑도 사용 가능

sort(dog.begin(),dog.end())는.. (참고로 sort는 반복자iterator를 사용함)

begin부터 end까지 정렬해달라는 아주 편리한 정렬기능을 제공해줌!!!!

짜잔~ 정렬된 것을 볼 수있다^^


하다보니 begin과 data의 차이가 궁금해져서..

array의 begin()과 data()의 차이

└ data()는 포인터를 반환,

begin()은 반복자(iterator)를 반환

 

**

반복자란? (iterator)

컨테이너의 요소를 하나씩 확인할 수있도록 해주는 것.

begin과 end는 반복자의 시작과 끝을 정의해주는거라고 생각하면됨.

반복자를 통해서 sort,find 알고리즘을 사용할 수 있다!!

포인터처럼 작동하지만.. 포인터와 비슷한 개념. 포인터보단 더 안전하게 사용 가능하대요

쉽게 말하면.. 반복자는 컨테이너 내에, 원소들을 전체적으로 훑어나갈 때 사용하는 것! 이라고 보면됨

**

이렇게 사용할 수 있다.. data()는 정말 첫번째 원소의 주소를 반환해주는 것이고,

begin()은 첫번째 원소를 가리키는 반복자임.

둘다 첫번째 원소에 관련되어있긴하나.. 엄연히 다르다~~


가장 큰 값을 찾기

stl에서는 std::max_element를 사용하면 반복자를 이용해

가장 큰 값의 위치를 찾아 반환해주는 아주 유~~용한 함수가 존재함

우린 이제 굳이 하나하나비교해가며 찾을 필요가 없다.. 기능이 제공되는데 뭐하러 직접 비교해?? 마인드


파일 입출력

std::ifstream, std::ofstream

예시로... 1000개의 랜덤 숫자를 파일에 저장. 하고 싶다고 할 때

└ std::ofstream -> 파일에 데이터를 쓰기 전용! (출력)

int1000개.txt 라는 파일이 없을 시엔 새 파일을 생성(연결)해줌. => 이때 중요한 개념.. RAII

 

**RAII (Resource Acquisition Is Initialization) 

cpp에서 자원의 획득을 객체의 생명주기와 결합하는 기법.

객체가 생성될 때 자원을 획득하고, 객체가 소멸될 때 자원을 자동으로 해제하도록 해줌.

* 생성자에서 자원을 획득, 소멸자에서 자원을 자동 해제.

파일입출력에서는.. 파일을 열고 닫을때 out.close() 를 안해줘도 된다. 불필요! (자동으로 close가 호출됨)

굳이 명시적으로 호출할 필요는 없다

RAII가 대신 해주기 때문!

(이거랑 관련된 건.. std::unique_ptr이 존재.. 이건 나중에 공부할것~~)

**

 

for (int num : a) {
print(out, "{:8}", num);
if (not (++i % 8))
out << std::endl;
}

을 통해... for문은 a에 시작부터 끝까지 돌며out에 num을 파일에 저장한다.!

 

└ std::ifstream -> 파일에서 데이터를 읽기 전용! (입력)

나같은 경우는.. 파일 예외 처리를 저렇게 해준다.. 근데 교수님이 내 코드 보더니 더 짧게 쓰라고하셔서 '넵'하고 바로 고침그냥 if(not in) 으로 바로 받으세요들

while(in >> num) 을 통해.. in에 있는 것들을 num으로 받아와 maxValue를 비교하는 while문을 돌린다

근데 이거랑 똑같은 기능을 하는게 바로 

std::max_element(std::istream_iterator<int>{in}, {});

(std::istream_iterator<int>{in}, {})를 이용해.. 파일에서 직접 값을 읽어오고, max_element값을 반환해줌!

위처럼 굳이 while문에서 in>>num을 통해 받아오지 않아도! 

스트림(in)으로부터 정수를 하나씩 바로 읽어옴~

 

끝...

글 하나 쓰는데 생각보다 오래걸림.. 이해가 느림+글을빨리못읽음+이것저것사이트뒤짐+사이트또들어가고또들어가고또들어가고의반복(거의뭔재귀함수)+개념하나를알려면그거에대한또다른개념을또알아야됨+집중력부족등등등..이슈로... 그래도 부지런히해야지 어 떡 해 ...