#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
using namespace std;
////////// "동적 배열 클래스" //////////
// 클래스 템플릿
template <typename T>
class dynamic_array {
T* data;
size_t n;
public:
// 매개변수 존재 생성자
dynamic_array(int n) {
this->n = n;
data = new T[n];
}
// 복사 생성자
// for deep copy
dynamic_array(const dynamic_array<T>& other) {
cout << "((((( 복사(복제) 생성자 호출 )))))" << endl;
n = other.n;
data = new T[n];
for (int i = 0; i < n; i++) {
data[i] = other[i];
}
}
// 복사 대입 연산자
dynamic_array& operator=(const dynamic_array& arr) {
cout << "((((( 복사(복제) 대입 연산자 호출 )))))" << endl;
n = arr.n;
data = new T[n];
for (int i = 0; i < n; i++) {
data[i] = arr[i];
}
return *this;
}
// non-const overloading
T& operator[](int index) {
return data[index];
}
// const overloading
const T& operator[](int index) const {
return data[index];
}
// 범위를 체크하는 at 함수
T& at(int index) {
if (index < n) {
return data[index];
}
throw "Index out of range";
}
// 배열의 크기 반환
size_t size() const {
return n;
}
// 소멸자에서는 메모리 누수를 방지하기 위해 할당된 메모리를 해제
~dynamic_array() {
delete[] data;
}
// 반복자 관련 함수
T* begin() {
return data;
}
const T* begin() const {
return data;
}
T* end() {
return data + n;
}
const T* end() const {
return data + n;
}
// friend 함수로 +연산자 함수 정의 (일반 함수를 통한 연산자 오버로딩)
/*
friend 키워드를 사용하여 +연산자 함수가 내 친구라는 것을 컴파일러에 알려줌
+연산자 함수에서는 dynamic_array 클래스의 private 멤버에 접근 가능
*/
friend dynamic_array<T> operator+(const dynamic_array<T>& arr1, const dynamic_array<T>& arr2) {
// (1) arr1.size() + arr2.size() 크기의 dynamic_array 생성
dynamic_array<T> result(arr1.size() + arr2.size());
// (2) arr1 복사
std::copy(arr1.begin(), arr1.end(), result.begin());
// (3) 이어서 arr2 복사
std::copy(arr2.begin(), arr2.end(), result.begin() + arr1.size());
cout << "+ 연산자 수행 완료" << endl;
return result;
}
// 배열에 저장된 모든 데이터를 문자열로 반환하는 to_string() 멤버 함수
string to_string(const string& sep = ", ") { // 기본 구분자는 쉼표(,)
if (n == 0)
return "";
ostringstream os;
os << data[0];
for (int i = 1; i < n; i++) {
os << sep << data[i];
}
return os.str();
}
};
///////////////////////////////////////////
////////// 학생 정보를 담을 구조체 //////////
struct student {
string name;
int standard;
};
// << 연산자를 이용한 표준 출력 지원
ostream& operator<<(ostream& os, const student& s) {
return (os << "[" << s.name << ", " << s.standard << "]");
}
///////////////////////////////////////////
// main
int main() {
int numOfStudent;
cout << "한 반의 학생수 입력: ";
cin >> numOfStudent;
// 동적배열 생성
dynamic_array<student> arr(numOfStudent);
for (int i = 0; i < numOfStudent; i++) {
string name;
int standard;
cout << i + 1 << "번째 학생의 이름: ";
cin >> name;
cout << "나이: ";
cin >> standard;
arr[i] = student{ name, standard }; // 구조체 생성
}
// 학생들 출력
//cout << arr.to_string() << endl;
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << endl;
}
cout << endl;
// 깊은 복사
cout << "arr = arr2, 깊은 복사" << endl;
auto arr2 = arr; // 복사(복제) 생성자 호출
for (int i = 0; i < arr2.size(); i++) {
cout << arr2[i] << endl;
}
cout << endl;
// 또는 cout << arr2.to_string() << endl;
// + 연산자 사용
auto arr3 = arr + arr2; // + 연산자 함수 반환 시 복사(복제) 생성자 호출
cout << "arr3 = arr + arr2, + 연산자 사용" << endl;
for (int i = 0; i < arr3.size(); i++) {
cout << arr3[i] << endl;
}
cout << endl;
// 또는 cout << arr3.to_string() << endl;
// 참고로 아래의 경우 복사 대입 연산자가 호출된다.
dynamic_array<student> arr4(arr.size());
arr4 = arr; // 복사(복제) 대입 연산자 호출
for (int i = 0; i < arr4.size(); i++) {
cout << arr4[i] << endl;
}
return 0;
}
void print() const {
cout << x << ", " << y << endl;
}
멤버변수를 읽기 전용으로 사용하겠다는 표시.
const Point operator+(const Point& rhs) const {
Point p;
p.x = this->x + rhs.x;
p.y = this->y + rhs.y;
return p;
}
복사 오버헤드 없이 참조하는 변수를 마찬가지로 읽기전용으로 사용하겠다는 표시.
함수의 반환값을 읽기 전용으로 사용하겠다는 표시.
reference: https://pmoncode.tistory.com/23
class Test {
private:
int m_i;
public:
// 기본 생성자(default constructor)
Test(){
this->m_i = 0;
cout << "call the default constructor" << endl;
}
// 복사 생성자(copy constructor)
Test(const Test &t) {
this->m_i = t.m_i;
cout << "call the copy constructor" << endl;
}
// 복사 대입 연산자(copy assignment operator)
Test& operator=(const Test &t) {
this->m_i = t.m_i;
cout << "call the copy assignment operator" << endl;
return *this;
}
};
int main() {
Test t1; // 기본 생성자 호출
Test t2(t1); // 복사 생성자 호출
Test t3 = t1; // 복사 생성자 호출
t1 = t2; // 복사 대입 연산자 호출
return 0;
}