예문
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Student {
private:
string name;
int score;
public:
Student(string n, int s) : name(n), score(s) {
cout << "Student 객체 생성: " << name << endl;
}
~Student() {
cout << "Student 객체 소멸: " << name << endl;
}
void printInfo() {
cout << "이름: " << name << ", 점수: " << score << endl;
}
};
int main() {
vector<unique_ptr<Student>> students;
students.push_back(make_unique<Student>("홍길동",100));
students.push_back(make_unique<Student>("돌쇠",90));
for (auto& student : students)
{
student->printInfo();
}
bool found = false;
for (const auto& student : students)
{
if (player->getName() == findName)
{
student->printInfo();
found = true;
break;
}
}
if (!found)
{
cout << "해당 이름의 학생을 찾을 수 없습니다." << endl;
}
return 0;
}
출력값
Student 객체 생성: 홍길동
Student 객체 생성: 돌쇠
이름: 홍길동, 점수: 100
이름: 돌쇠, 점수: 90
Student 객체 소멸: 홍길동
Student 객체 소멸: 돌쇠
사용된 개념 정리
1. 초기화 리스트
Student(string n, int s) : name(n), score(s) {}
생성자 함수에서 생성자가 실행되기 전에 멤버변수를 초기화 해준다.
그냥 생성자 본문 안에서 대입하는 것보다 성능도 좋고, 코드도 깔끔해진다.
특히 const 멤버 변수나 참조형 멤버 변수는 초기화 리스트로만 초기화 할 수 있다.
2. 스마트 포인터 (unique_ptr)
vector<unique_ptr<Student>> students;
students.push_back(make_unique<Student>("홍길동",100));
students.push_back(make_unique<Student>("돌쇠",90));
- unique_ptr<Student> : uniuqe_ptr<데이터타입> 으로 스마트포인터 변수를 선언하고
- make_unique<Student>("홍길동",100) : make_unique<데이터타입>(매개변수값) 으로 객체를 생성해서 초기화 한다.
- 스마트 포인터는 개발자가 일일이 delete를 하지 않아도 되기 때문에, 메모리 누수 문제나 잘못된 메모리접근 문제를 줄일 수 있다.
- #include <memory> 추가 필요.
※ 객체 생성에는 여러가지 방법이 있다.
1) 포인터틀 사용하지 않고, 동적할당을 하지 않으며 바로 복사해서 사용하는 경우.
Student s("홍길동",100)
s.printInfo();
- 객체의 메모리가 크지 않으며, 함수 안에서만 간단하게 사용할 때는 이렇게 사용해도 괜찮다.
- 객체를 stack공간에 생성한다. 함수가 끝나도 계속 존재해야 하는 객체에는 적합하지 않다.
2) 포인터를 사용하여 동적할당을 사용하는 경우.
Student* s = new Student("홍길동",100)
s->printInfo();
delete s;
- 객체를 heap공간에 생성한다. 이 메모리는 delete 해주지 않는 이상 사라지지 않는다.
- 프로그램 실행 중에 필요한 만큼 메모리를 할당하거나 해제할 수 있어서 유연하게 사용할 수 있다.
- 특별한 이유가 없다면 스마트 포인터를 사용하는 게 훨씬 좋다.
// 스마트포인터 사용예시
unique_ptr<Student> s = make_unique<Student>("김지혜", 98);
3. 벡터
- 벡터 선언 : vector <데이터타입> 벡터이름;
- 벡터에 객체 입력 : 벡터이름.push_back(객체명(객체매개변수값));
vector<unique_ptr<Student>> students;
students.push_back(make_unique<Student>("홍길동",100));
students.push_back(make_unique<Student>("돌쇠",90));
※ 자주쓰는 벡터 명령어
- push_back() : 벡터의 맨 뒤에 괄호 안의 요소를 추가한다.
- pop_back() : 벡터의 맨 뒤에 있는 요소를 제거할 때 사용한다.
- size() : 벡터에 현재 몇 개의 요소가 들어있는지(크기)를 알고 싶을 때 사용한다.
- empty() : 벡터가 비어있는지 확일할 때 사용한다. 비어있으면 true를 반환한다.
- at() 또는 [ ] : 벡터 안에 특정 위치에 있는 요소에 접근할 때 사용한다. at()은 범위를 벗어나는 인덱스를 접근할 때 범위검사를 먼저하여 예외를 발생시켜서 더 안전하게 사용할 수 있다.
- clear() : 벡터 안의 모든 요소를 한 번에 제거한다.
- front() : 첫 번째 요소 접근.
- back() : 마지막 요소 접근.
- erase() :
- 1) 특정 위치 하나 삭제 : v.erase(v.begin() + 인덱스)
- 2) 범위 삭제 : v.erase(시작 반복자, 끝 반복자)
4. 범위 기반 for 루프 (range-based for loop)
: students 벡터의 처음부터 끝까지 각 요소를 하나씩 순회하면서 student 변수에 참조로 연결해준다.
전통적인 방식
for(size_t i = 0; i < students.size(); i++)
{
const unique_ptr<Student>& student = students[i];
student->printInfo();
}
범위 기반 for 문
for(const auto& student : students)
{
student->printInfo();
}
5. 이름을 검색하여 해당 이름의 정보 출력하기
- bool 변수를 생성해 이름을 찾았는지 여부를 체크해준다. 이름을 못 찾을 경우 예외문을 출력한다.
- 범위 기반 for 문을 통해 벡터를 순회하여 조건에 맞는 요소를 하나씩 비교해본다.
- name 은 get함수를 통해 값을 가져와서 findName과 비교해준다.
'C++ 공부' 카테고리의 다른 글
| istringstream (1) | 2025.10.01 |
|---|---|
| 최대공약수와 최소공배수를 구하는 함수 (0) | 2025.09.29 |
| OOP_Project01_BankAccount(은행계좌관리프로그램 만들기) (0) | 2025.09.05 |
| C++ 기초_디자인패턴_싱글톤 패턴 (3) | 2025.09.05 |
| 인터페이스와 추상클래스의 차이점 (0) | 2025.09.02 |