인프런 커뮤니티 질문&답변

구병주님의 프로필 이미지

작성한 질문수

홍정모의 따라하며 배우는 C++

10.6 컨테이너 클래스

컨테이너 클래스 피드백 부탁드립니다.

작성

·

21

1

 

#include <iostream>

#include <vector>

using namespace std;

class IntArray {

private:

int m_length = 0;

int* m_data = nullptr;

public:

//생성자

IntArray(const std::initializer_list<int> &list)

:m_length(list.size()){

m_data = new int[m_length];

int i = 0;

for (auto n : list) {

m_data[i++] = n;

}

}

//copy constructor

IntArray(const IntArray& copy)

:m_length(copy.m_length){

for (int i = 0; i < m_length; i++) {

m_data[i] = copy.m_data[i];

}

}

IntArray operator = (const IntArray source) {

if (this == &source) {

return *this;

}

delete[] m_data;

m_length = source.m_length;

if (source.m_data != nullptr) {

m_data = new int[m_length];

for (int i = 0; i < m_length; i++) {

m_data[i] = source.m_data[i];

}

}

else {

m_data = nullptr;

}

return *this;

}

friend ostream& operator<<(ostream& out, IntArray& arr) {

for (unsigned i = 0; i < arr.m_length; i++) {

out << arr.m_data[i] << " ";

}

out << endl;

return out;

}

//reset

void reset() {

delete[] m_data;

m_length = 0;

m_data = nullptr;

}

//resize

void resize(int new_length) {

if (m_length == new_length) {

return;

}

int* len = new int[new_length];

int temp = m_length > new_length ? new_length : m_length;

for (int i = 0; i < temp; i++) {

len[i] = m_data[i];

}

delete[] m_data;

m_data = len;

m_length = new_length;

}

void insertBefore(const int& pushNum, const int& indexNum) {

if (indexNum<0 || indexNum > m_length) {

return;

}

int* temp = new int[m_length + 1];

for (int i = 0; i < indexNum; i++) {

temp[i] = m_data[i];

}

temp[indexNum] = pushNum;

for (int i = indexNum; i < m_length; i++) {

temp[i + 1] = m_data[i];

}

delete[] m_data;

m_data = temp;

++m_length;

}

void remove(const int& indexNum) {

if (indexNum<0 || indexNum >= m_length) {

return;

}

int* temp = new int[m_length - 1];

for (int i = 0; i < indexNum; i++)

{

temp[i] = m_data[i];

}

for (int i = indexNum + 1; i < m_length; i++) {

temp[i - 1] = m_data[i];

}

delete[] m_data;

m_data = temp;

--m_length;

}

void push_back(const int& num) {

resize(m_length + 1);

m_data[m_length - 1] = num;

}

//소멸자

~IntArray()

{

if (m_data != nullptr) {

reset();

}

}

};

int main()

{

//초기화

IntArray my_arr{ 1,3,5,7,9 };

cout << my_arr << endl;

// 10을 인덱스 1앞에 : 1, 10, 3, 5, 7, 9 출력까지

my_arr.insertBefore(10, 1);

cout << my_arr << endl;

// 인덱스 3 제거, 메모리 제거까지? 1 10 3 7 9

my_arr.remove(3);

cout << my_arr << endl;

// 사이즈 추가? 1 10 3 7 9 13

my_arr.push_back(13);

cout << my_arr << endl;

return 0;

}

insertBefore, remove에서 for문을 두번씩 사용하고 전체적으로 for문으로 많이 사용하는게 좀 걸리긴하는데 더 나은 방법이 있으면 얼마든지 알려주시면 감사하겠습니다!!

답변 1

1

안녕하세요? 질문&답변 도우미 Soobak 입니다.

 

과제에서 명시적으로 요구된 내용에서 더 나아가 복사 생성자와 대입 연산자오버로딩까지 챙기며 구현하려 하신 부분이 훌륭하시네요.

다만, 이 과정에서 조금 아쉬운 부분이 있는 것 같습니다.
우선, 복사 생성자에서 메모리 할당이 누락되어 있어 복사 과정에 오류가 발생하게 됩니다.

IntArray(const IntArray& copy)
  :m_length(copy.m_length)
{
  for (int i = 0; i < m_length; i++)
  {
    m_data[i] = copy.m_data[i];    // m_data가 할당되지 않은 상태에서 접근하게 됩니다.
  }
}

: m_data 는 메모리의 할당되어있지 않기 때문에 오류가 발생합니다.

 

또한, 대입 연산자 오버로딩에 있어서 매개변수의 자료형과 반환 자료형이 값으로 되어있는 부분도
참조로 변경하시는 것이 좋습니다. 불필요한 복사 문제와 자기 대입 시 메모리 관리가 엉키는 문제 등을 방지하기 위함입니다.

복사 생성자를 사용하는 코드를 추가하여 프로그램을 실행시켜 보시면 바로 문제점을 쉽게 파악하실 수 있으실 것 같습니다.
(만약, 이해가 어려우시면 강의 9.11 대입 연산자 오버로딩, 깊은 복사, 얕은 복사 부분 를 참고해보시면 도움이 되실 것 같습니다.)

나머지 부분은 잘 구현하셨습니다.
반복문을 많이 사용하시는 부분을 걱정하셨지만, 지금의 학습 단계에서 훌륭하게 작성하셨다고 생각합니다.

추후에 다양한 알고리듬과 자료구조를 학습하시면서 더욱 발전하실 수 있으실 것 같습니다.

 

추가적으로, 더 나은 방법에 대해 궁금증을 갖고 계신 것 같으셔서, 생각난 재밌는 내용을 간단히 소개드려봅니다.

: 컴파일러마다 구현 내용은 조금씩 다르지만, 데이터 추가 가능성이 있는 컨테이너의 경우 최초, 혹은 resize() 를 통한 메모리 할당을 '명시된 크기' 보다 조금 더 많이 할당을 해놓습니다.
따라서, push_back() 혹은 insert() 과정에 있어서 이미 할당된 메모리 공간이 충분하다면 매번 '추가되는 데이터의 개수' 만큼 메모리 할당을 진행하지 않고, 비어있는 메모리 공간에 값을 추가합니다.
그러다가, 비어있는 메모리 공간이 더 이상 없는 경우 또 여유롭게 메모리 할당을 진행합니다.
얼마나 여유롭게 메모리를 할당할지는 컴파일러마다 다르고, 이 과정에 있어서 현재 힙에 할당이 가능한 메모리 공간이 충분한지도 체크하여 예외를 처리하는 등 재미있지만 조금 복잡한 과정 등으로 STL 의 컨테이너들이 구현되고는 합니다. 이외에도 효율성, 최적화를 위해 참 신기하게 구현된 부분이 많으니, 추후 여유가 되신다면 g++ 혹은 clang 등의 컴파일러에서 구현된 STL 의 컨테이너 클래스를 들여다보시는 것도 좋은 학습이 되실 것 같습니다.

응원합니다!