Develop/C, C++

[C++] 객체 배열과 벡터

2023. 12. 22. 12:11
목차
  1. 1. 객체 배열
  2. 2. 객체 배열의 초기화
  3. 3. 객체 배열 예제
  4. 예제1 : 책들을 저장해보자
  5. 예제 2 : 원들을 저장하자
  6. 4. 벡터
  7. 5. 벡터의 선언
  8. 6. 벡터 대표 예제
  9. 7. push_back()과 pop_back()
  10. 8. 벡터에서 요소의 위치 : v.begin() / v.end() / v.front() / v.back()
  11. 9. 벡터의 중간 부분을 삭제하기 : erase()
  12. 10. 벡터와 연산자
  13. 11. 벡터 예제
  14. 예제1 : 벡터에 문자열 저장하자
  15. 예제2 : 벡터에 Circle 객체를 저장하자
  16. 예제3 : 벡터와 알고리즘(정렬)
  17. 예제4 : 성적평균을 계산하자
  18.  
  19. 예제5 : 영화정보를 저장하자
  20. 12. array 클래스
728x90
C/C++

이번 포스팅에서 우리가 배워볼 것은 다음과 같다.

  1. 객체 배열
  2. 객체 배열의 초기화
  3. 객체 배열 예제
  4. 벡터
  5. 벡터의 선언
  6. 벡터 대표 예제
  7. push_back()과 pop_back()
  8. 벡터에서 요소의 위치 : v.begin() / v.end() / v.front() / v.back()
  9. 벡터의 중간 부분을 삭제하기 : erase()
  10. 벡터와 연산자
  11. 벡터 예제
  12. array 클래스

1. 객체 배열

  • 정수 배열을 생성할 수 있는 것처럼 객체들의 배열도 생성 가능하다!
  • 객체 배열의 요소가 객체가 된다. 즉, 객체들이 모여 있는 컨테이너가 '객체 배열'이 되는 셈이다!
  • 아래 예제를 통해서 원을 나타내는 객체를 여러개 생성하여서 화면에 그려보는 프로그램을 작성해보자.
  •  
  • #include <iostream> using namespace std; class Circle { public: int x, y; int radius; Circle() : x{0}, y{0}, radius{0} {} // 초기화 리스트를 이용한 기본생성자 Circle(int x, int y, int r) : x{x}, y{y}, radius{r} {} // 인수가 있는 생성자 void print() { cout << "반지름: " << radius << " @(" << x << "," << y << ")" << endl; } }; int main(void) { Circle objArray[10]; for (Circle &c : objArray) { c.x = rand() % 500; c.y = rand() % 300; c.radius = rand() % 100; } for (Circle c : objArray) c.print(); return 0; }
  • 출력 결과 값
    만일 객체 배열이 없었으면 아래처럼 너무 힘들게 코드를 작성했을 것이다...
Circle c1;
Circle c2;
Circle c3;
...

2. 객체 배열의 초기화

  • 각 배열 요소별로 생성자를 호출하면 객체 배열 안의 객체들을 서로 다르게 초기화가 가능하다.
  • 일반 배열과 같은 초기화 형태를 가지지만, 값 대신에 생성자를 호출한다.
Circle objArray[10] = {
	Circle(100, 100, 30),
    Circle(100, 200, 50),
    Circle(100, 300, 80),
    ...
   }

 

3. 객체 배열 예제

예제1 : 책들을 저장해보자

여러 권의 책을 저장할 수 있는 객체 배열 books를 생성하여 보자.

#include <iostream>
using namespace std;

class Book {
public:
  string title;
  int price;
  Book(string name, int price) : title{name}, price{price} {}
  void print() { cout << "제목: " << title << ",  가격 : " << price << endl; }
};

int main(void) {
  Book objArray[2] = {Book("금도끼 은도끼", 5000), Book("C++ 교재", 10000)};
  cout << "소장하고 있는 책 정보" << endl;
  cout << "===================" << endl;
  for (Book b : objArray)
    b.print();
  cout << "===================" << endl;
  return 0;
};

출력 결과 값

 

예제 2 : 원들을 저장하자

  • 10개의 원을 저장할 수 있는 배열을 선언하고 사용자가 키 'c'를 누르면 각각의 원의 위치와 반지름을 난수로 초기화한 후에 화면에 그린다. 사용자가 키 'q'를 누르면 프로그램을 종료한다.
  •  
#include <Windows.h>
#include <conio.h>	//consol i/o
#include <iostream>

using namespace std;

class Circle {
public:
	int x, y;
	int radius;
	Circle() : x{ 0 }, y{ 0 }, radius{ 0 } {}
	Circle(int x, int y, int r) : x{ x }, y{ y }, radius{ r } {}
	void draw() {
		int r = radius / 2;
		HDC hdc = GetWindowDC(GetForegroundWindow());
		Ellipse(hdc, x - r, y - r, x + r, y + r);
	}
};

int main(void) {
	Circle objArray[10];

	while (true) {
		for (Circle& c : objArray) {
			c.x = rand() % 500;
			c.y = rand() % 300;
			c.radius = rand() % 100;
			c.draw();
		}
		char ch = _getch();
		if (ch == 'q') break;
	}
	return 0;
}

출력 결과 값

 

4. 벡터

  • 벡터(vector)는 동적 배열이다.
  • 컴파일 시간에 배열의 크기를 미리 결정할 필요가 없다.
  • 추가되는 요소의 개수에 따라서 자동적으로 크기가 조절된다.

5. 벡터의 선언

  • 사용법 : 클래스 이름 뒤에 <>를 붙인 후 원하는 자료형 기입
  • 클래스 템플릿으로 구현된 일종의 클래스이다.
  • 클래스 인스턴스를 선언하는데 타입을 지정할 수 있다고 생각하면 쉽다
    • vector<int> scores(10); //배열의자료형 배열의이름(배열의크기);
      score[2] = 78; // indexing 배열과 동일하게 가능함.
      cout << score[2] << endl; // 결과값 : 78

6. 벡터 대표 예제

  •  
  • #include <iostream> #include <vector> using namespace std; int main(void) { vector<int> fibonacci{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; for (auto &number : fibonacci) { cout << number << ' '; } cout << endl; return 0; }
  • 출력 결과 값

7. push_back()과 pop_back()

  • push_back()은 공백 벡터에서 시작하여서 하나씩 추가될 때마다 벡터의 크기를 확대한다.
  • push_back() 사진 추가
  • pop_back()은 push_back()과 반대 기능을 하는 함수이다.
  • 벡터의 끝에서 요소를 제거하고 벡터의 크기를 하나 감소한다.
  • 요소를 반환하지 않음으로 삭제하기 전에 미리 삭제할 요소를 다른 곳에 저장해야 한다. (파이썬과 다른 점)
  • pop_back() 사진 추가
  • 아래 예제 2개를 통해서 를 통해 확인해보자.
  • #include <iostream> #include <vector> using namespace std; int main(void) { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); cout << "v1 = "; for (auto& e : v1){ cout << e << " "; } cout << endl; return 0; }

출력 결과 값

 

#include <iostream>
#include <vector>
using namespace std;

int main(void) {
  vector<int> v;
  for (int i = 0; i < 10; i++) {
    v.push_back(i);
  }

  cout << "현재의 v = ";
  for (auto &e : v)
    cout << e << " ";
  cout << endl;

  cout << "삭제 요소 = ";
  // 벡터가 공백이 될 때까지 pop_back() 호출
  while (v.empty() != true) {
    cout << v.back() << " ";
    v.pop_back();
  }
  cout << endl;
  return 0;
}

출력 결과 값

8. 벡터에서 요소의 위치 : v.begin() / v.end() / v.front() / v.back()

  • 벡터에서 요소의 위치는 반복자(iterator)를 이용하여 표시한다.
  • v.begin()은 벡터의 시작 주소, v.end()는 벡터의 마지막 주소를 가리킨다.
  • v.front()는 벡터의 첫 번째 요소, v.back()는 벡터의 마지막 요소를 반환한다.
  • v.begin()으로 식별되는 요소는 시퀀스의 일부이지만, v.end()는 시퀀스의 끝을 하나 넘는 요소이니 주의하자.
  • 반복자가 중요한 이유는 벡터 안의 요소들을 가리킬 수 있기 때문이다.

v.begin() 과 v.end()

for(auto p = v.begin(); p != v.end(); ++p)
	cout << *p << endl;
// p는 포인터값, *p는 실제 값

 

9. 벡터의 중간 부분을 삭제하기 : erase()

  • 벡터는 동적 배열이기 때문에 배열의 중간에서 요소를 삭제할 수 있다.
  • 벽돌 깨기 게임
  • 위의 그림과 같이 중간에 있는 벽돌이 공에 의해 충돌하게 되면 우리는 벡터의 중간에서 삭제해야 한다.
  • 이 때 사용되는 함수는 erase() 함수이다.
  • 삭제하려는 요소의 인덱스가 i라고 한다면 아래의 코드 문장으로 i번째 요소를 삭제할 수 있다.
v.erase(v.begin() + i);

 

10. 벡터와 연산자

  • std::vector에서 == 연산자는 요소 단위로 비교하지 않는다. 대신 두 벡터가 같은 메모리를 가리키는지를 비교한다.
  • 두 벡터가 같은지 확인하려면 == 연산자를 사용할 수 있지만, 이것은 두 벡터의 메모리 주소가 같은지를 비교하는 것이며, 벡터 내의 요소 값이 같은지를 비교하는 것이 아니다.
  • 때문에 정확한 요소 단위 비교를 위해서는 별도의 루프나 사용자 정의 함수를 통해 요소를 비교해야 한다.
#include <iostream>
#include <vector>
using namespace std;

int main(void) {
  vector<int> v1{1, 2, 3, 4, 5};
  vector<int> v2(v1);  // 다른 벡터를 인수로 받아 초기화하는 생성자가 있을 것이다.

  if(v1 == v2) {
    cout << "2개의 벡터가 일치합니다." << endl;
  }
  return 0;
}

결과

11. 벡터 예제

예제1 : 벡터에 문자열 저장하자

#include <iostream>
#include <vector>
using namespace std;

int main(void) {
  vector<string> vec;    // 벡터를 생성한다.

  vec.push_back("MILK");  // 벡터의 끝에 자료를 저장한다.
  vec.push_back("BREAD");
  vec.push_back("BUTTER");
  for(auto e: vec){
    cout << " " << e;
  }
  cout << endl;
  return 0;
}

결과

 

예제2 : 벡터에 Circle 객체를 저장하자

#include <iostream>
#include <vector>
using namespace std;

class Circle{
public:
  int x, y;
  int radius;
  Circle() : x{0}, y{0}, radius{0}{}
  Circle(int x, int y, int radius) : x{x}, y{y}, radius{radius}{}
  void print() {
    cout << "반지름: " << radius << " @(" << x << ", " << y << ")" << endl;
  }
};

int main(void) {
  vector<Circle> objArray;

  for(int i = 0; i < 10; i++){
    Circle obj{rand() % 300, rand() % 300, rand() % 100};
    objArray.push_back(obj);
  }
  for (Circle c : objArray)
    c.print();
  return 0;
}

결과

예제3 : 벡터와 알고리즘(정렬)

  •  sort(배열의 시작점 주소, 배열의 끝점 주소, (선택)) 함수 : 기본적으로 오름차순 정렬
  • (선택)에다가 compare 함수를 만들어서 sort()의 세 번째 인자 값으로 넣게 되면, 해당 함수의 반환 값에 맞게 정렬이 동작된다.)
  •  
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

class Person{
private: 
  string name;
  int age;
public:
  Person(string n, int a){
    name = n;
    age = a;
  }
  string get_name() {return name;}
  int get_age() {return age;}
  void print(){
    cout << name << " " << age << endl;
  }
};

bool compare(Person &p, Person &q){
  return p.get_age() < q.get_age();
}

int main(void) {
  vector<Person> list;

  list.push_back(Person("Kim", 30));
  list.push_back(Person("Park", 22));
  list.push_back(Person("Lee", 26));

  sort(list.begin(), list.end(), compare);

  

  for(auto& e : list){
    e.print();
  }
  return 0;
}

결과

예제4 : 성적평균을 계산하자

  • 학생들의 평균 성적을 계산하는 예제에서 학생이 몇 명인지 알 수 없다고 하자. 동적 배열인 벡터를 이용하여서 작성해보자.
  • 결과
  • Tip) 공백 벡터를 선언하고 사용자가 -1을 입력할 때까지 push_back() 함수를 호출하여 벡터에 성적을 추가한다. 입력이 종료되면 범위 기반 for 루프를 이용하여서 벡터에서 요소를 하나씩 꺼내서 평균을 계산한다.
  • 결과 코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

int main(void) {
  vector<int> scores;
  int score;
  int sum = 0;
  double avg;
  
  while (true) {
    cout << "성적을 입력하시오(종료는 -1) : ";
    cin >> score;
    if (score == -1) {
      break;
    }
    scores.push_back(score);
  }

  
  for(auto& s : scores){
    sum += s;
    avg = sum / scores.size();
  }

  cout << "성적 평균=" << avg << endl;
  return 0;
}

 

예제5 : 영화정보를 저장하자

  • 벡터를 이용하여 영화에 대한 정보를 저장했다가 출력하는 프로그램을 작성해보자.
  • 결과
  • 정답 코드
  •  
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Movie {
private:
  string title;
  double rating;

public:
  Movie(string t = "", double r = 0.0) {
    title = t;
    rating = r;
  }
  void print_movie() { cout << title << ": " << rating << endl; }
};

int main(void) {
  vector<Movie> movies;
  movies.push_back(Movie("titinic: ", 9.9));
  movies.push_back(Movie("gone with the wind: ", 9.6));
  movies.push_back(Movie("terminator: ", 9.7));

  for (auto &m : movies) {
    m.print_movie();
  }
  return 0;
}

 

12. array 클래스

  • vector는 생성과 소멸을 하는데 상당한 시간이 소요된다. 따라서 vector의 장점이 많지만 성능 때문에 기존의 배열을 사용하는 경우도 많다.
  • 이 문제를 해결하기 위해 C++11 에서는 std::array를 새롭게 제시하였다.
  • array 클래스를 사용하면 벡터의 장점과 기존 배열의 성능을 동시에 누릴 수가 있다.(C++에서는 항상 성능(속도)를 중요시한다.)
  • array 클래스는 기존의 배열보다 다양한 함수를 제공한다.
    • size() : 배열의 크기
    • fill() : 배열의 모든 원소를 동일한 값으로 채움
    • empty() :  배열이 비어있는지 검사
    • at() : 배열의 요소에 접근할 때 사용
    • front() : 배열의 첫 번째 요소
    • back() : 배열의 마지막 요소
  • array 클래스 예제
  • #include <iostream>
    #include <array>
    
    using namespace std;
    
    int main(){
      array<int, 3> list{1, 2, 3};
    
      for (int i = 0; i < list.size(); i++){
        ++list[i];
      }
    
      for (auto& elem : list)
        cout << elem << " ";
      cout << endl;
    
      return 0;
    }

결과

 

저작자표시 (새창열림)

'Develop > C, C++' 카테고리의 다른 글

[C/C++] 객체 지향 프로그래밍과 클래스  (0) 2023.12.25
[C/C++] 생성자(constructor) & 접근 제어(access control)  (0) 2023.12.23
[C/C++] 상속(Inheritance)  (0) 2023.12.19
[C/C++] 동적할당(Dynamic Memory Allocation)  (0) 2023.12.18
[C/C++] 문자열(String)  (0) 2023.12.18
  1. 1. 객체 배열
  2. 2. 객체 배열의 초기화
  3. 3. 객체 배열 예제
  4. 예제1 : 책들을 저장해보자
  5. 예제 2 : 원들을 저장하자
  6. 4. 벡터
  7. 5. 벡터의 선언
  8. 6. 벡터 대표 예제
  9. 7. push_back()과 pop_back()
  10. 8. 벡터에서 요소의 위치 : v.begin() / v.end() / v.front() / v.back()
  11. 9. 벡터의 중간 부분을 삭제하기 : erase()
  12. 10. 벡터와 연산자
  13. 11. 벡터 예제
  14. 예제1 : 벡터에 문자열 저장하자
  15. 예제2 : 벡터에 Circle 객체를 저장하자
  16. 예제3 : 벡터와 알고리즘(정렬)
  17. 예제4 : 성적평균을 계산하자
  18.  
  19. 예제5 : 영화정보를 저장하자
  20. 12. array 클래스
'Develop/C, C++' 카테고리의 다른 글
  • [C/C++] 객체 지향 프로그래밍과 클래스
  • [C/C++] 생성자(constructor) & 접근 제어(access control)
  • [C/C++] 상속(Inheritance)
  • [C/C++] 동적할당(Dynamic Memory Allocation)
JuniTech
JuniTech
프로그래밍을 정복하기 위한 좌충우돌 코린이의 기록
JuniTech
Juni IT Technology
JuniTech
전체
오늘
어제
  • 분류 전체보기 (84)
    • Develop (29)
      • C, C++ (13)
      • Python (9)
      • Java (1)
      • JavaScript (0)
      • Arduino Uno (6)
    • CodingTest (38)
      • Baekjoon (36)
    • Project (0)
    • IT Issue (1)
    • Computer Science (11)
      • 프로그래밍 언어론 (3)
      • Open Source (3)
      • Data Structure (5)
    • Paper (0)
    • AI (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 🧑‍💻Github
  • 😎Juni의 잡동사니(일상 블로그)
  • 💰Juni의 투자일기(주식 블로그)

공지사항

인기 글

태그

  • LCD
  • 27866
  • 13241
  • 10810
  • C
  • 25206
  • 아두이노 우노
  • Backjoon
  • 10988
  • 프로그래밍 어론
  • c++
  • 파스트리
  • 백준
  • 10813
  • 파이썬
  • pygame
  • 문자열
  • 10798
  • 10812
  • Python
  • 프로그래밍어론
  • 프어론
  • 2083번
  • 프로그래밍 역사
  • 10811
  • 10797
  • 구문법
  • 생존시간
  • 포인터
  • 11000

최근 댓글

최근 글

hELLO · Designed By 정상우.
JuniTech
[C++] 객체 배열과 벡터
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.