Kvector Class를 만들어보자_1편

gcoco·2023년 5월 6일
0

안녕하세요! 뜨끈한 국밥을 참 좋아하는 GCOCO입니다!🥘🍲🥘🍲


잡설 한 COOKIE🍪

오늘은 가족과 함께 점심에 장암에 있는 국밥집을 다녀왔습니다!
근방에서 꽤나 규모가 거대하고 맛있는 국밥집이기에 비오는 날임에도 불구하고 많은 손님들이 있더군요.
심지어 줄을 서서까지 먹는걸 보니 놀라운 광경이었습니다.
그렇게 거대한 규모의 국밥집에 사람이 다 차고 그마저도 부족하여 대기줄이 있는 모습이란 ㄷㄷ

암튼 국밥 조아!

이번 포스팅은 학교 수업에서 진행하는 Kvector라는 Class를 만들어 나가는 과정을 기록하는 첫번째 단계입니다!
진도에 맞추어 저도 이 과제를 업데이트 할 예정입니다!

과제를 진행하며 포인트가 될만한 부분들의 팁을 적어놓도록 하겠습니다.

가시죠. 어서!


바로 코드부터 가겠습니다!

#include <iostream>
#include <cstring>

using namespace std;

class Kvector {
	int* m;
	int len;
public:
	Kvector(int sz = 0, int value = 0);
	Kvector(const Kvector& v);
	~Kvector() {
		cout << this << " : ~Kvector() \n";
		delete[] m;
	}
	void print() {
		for (int i = 0; i < len; i++)
			cout << m[i] << " ";
		cout << endl;
	}
	void clear() {
		delete[] m;
		m = nullptr;
		len = 0;
	}
	int size() { return len;}

};

Kvector::Kvector(int sz, int value) {
	len = sz;
	cout << this << " : Kvector( "<<sz<<", "<<value<<")\n";
	if (sz == 0) {
		m = nullptr;
	}
	else {
		m = new int[sz];
		for (int i = 0; i < len; i++) {
			m[i] = value;
		}
	}
}

Kvector::Kvector(const Kvector& v) {
	cout << this << " : Kvector(" << &v << ")\n";
	len = v.len;
	if (len == 0) {
		m = nullptr;
	}
	else {
		m = new int[len];
		for (int i = 0; i < len; i++) {
			m[i] = v.m[i];
		}
	}
}

int main() {
	Kvector v1(3); v1.print();
	Kvector v2(2, 9); v2.print();
	Kvector v3(v2); v3.print();
	v2.clear();
	v2.print();
	v3.print();

	return 0;
}

이번 과제의 목표는 Kvector class 내의 아래의 두 부분을 class 외부에 구현하는 문제였습니다.

Kvector(int sz = 0, int value = 0);
Kvector(const Kvector& v);

문제의 핵심은 '생성자와 복사생성자를 잘 구현할 수 있겠느냐?' 였습니다.

구현부를 같이 보며, 포인트를 짚어보죠.

Kvector::Kvector(int sz, int value) {
	len = sz;
	cout << this << " : Kvector( "<<sz<<", "<<value<<")\n";
	if (sz == 0) {
		m = nullptr;
	}
	else {
		m = new int[sz];
		for (int i = 0; i < len; i++) {
			m[i] = value;
		}
	}
}

먼저 생성자의 body입니다. class 내부의 선언에선 default argument값이 들어가있는 반면 body에서는 없는모습을 확인할 수 있었습니다. 이는 body에서도 default argument값이 들어가면 '기본인수의 재정의'라는 오류와 함께 제대로 작동하지 않음을 확인할 수 있습니다. 따라서 default argument를 제거하고 인자만 넘겨주도록 합니다.
이후 sz, 즉 사이즈에 따라 m에 동적할당을 받을지 말지를 결정하는 내용의 코드입니다.

다음은 복사생성자에 관한 내용입니다.

Kvector::Kvector(const Kvector& v) {
	cout << this << " : Kvector(" << &v << ")\n";
	len = v.len;
	if (len == 0) {
		m = nullptr;
	}
	else {
		m = new int[len];
		for (int i = 0; i < len; i++) {
			m[i] = v.m[i];
		}
	}
}

이 부분에서 눈 여겨볼 점은 '깊은 복사의 수행'입니다. 위 과제에서 m같은 경우 int* type인데, 디폴트 복사생성자를 이용하게 되면 얕은복사를 수행하게 되고 이는 복사된 새로운 Kvector의 m과 복사 대상이 같은 주소를 가리키게 되어 동적할당 해제시 문제가 발생하게 됩니다! 따라서 깊은 복사를 수행하기 위한 복사생성자가 반드시 필요한 상황입니다.

그렇기에 const를 이용하여 v의 정보만 읽어와 len을 복사를 하고 len의 길이가 0이라면 m=nullptr로 초기화 해주었으며 만약 len의 길이가 양수일 시 새롭게 동적할당을 받아 고유의 주소를 갖도록 해 주었습니다.


이번 포스팅은 여기서 마치며 추후에 class의 개념에 대한 포스팅들을 다뤄보도록 하겠습니다.

감사합니다 ^_^;

profile
그코코 입니다.

0개의 댓글