Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- BOJ 2098
- yolo
- 외판원 순회
- 그리디 알고리즘
- 인간이 그리는 무늬
- 위상정렬
- 성화봉송주자
- MST
- 안드로이드 스튜디오
- 다음 지도 api
- 캘리그라피
- 영어회화 100일의 기적
- 창훈쓰다
- 다이나믹 프로그래밍
- 성화봉송
- boj
- 다음 API
- 생활코딩
- lower_bound
- 이분탐색
- upper_bound
- 언어의 온도
- multiset
- BFS
- DP
- 삼성 코딩테스트
- 평창동계올림픽
- Segment Tree
- 비트마스크
- 백트레킹
Archives
- Today
- Total
Hoon222y
[1218-4] 기본 생성자 , 멤버 이니셜라이저, 복사 생성자의 종류 본문
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //기본 생성자 #include <iostream> using namespace std; class Point{ int _x, _y; //사용자가 생성자를 추가하지 않으면 컴파일러가 생성자를 자동으로 추가하는데 //이를 기본생성자(default constructor)라고 한다. public: //만약 사용자가 생성자를 추가한다면 컴파일러는 기본 생성자를 추가하지 않는다. //이는 초기화되지 않은 객체 사용으로 인하여 프로그램이 불안정해지는것을 막기 위해서이다. //즉 아래에서 인자 2개짜리 하고 Point(){}를 없애면 main 문에서 Point p1은 에러가 발생한다. //원래는 따로 생성자를 안해도 Point p1은 오류 안남. Point(){} Point(int x, int y){ _x = x; _y = y; } }; int main(){ Point p1; //인자가 없는 생성자를 사용하여 객체를 생성하는 코드 Point p2(1, 2); //인자가 2인 생성자를 사용하여 객체를 생성하는 코드 } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #if 0 //멤버 이니셜라이져 #include <iostream> using namespace std; class Circle{ int _x, _y; int _radius; const double PI; public: //맴버 이니셜라이저 : 맴버를 초기화 하고 싶다면 사용한다. //시용방법은 생성자() : 멤버(값), 멤버2(값) , ... Circle() : PI(3.14) { //생성자 내부에서 맴버에 대하여 값을 대입하는 값을 설정하는 것은 //초기화가 아니라 대입니다. _x = _y = _radius = 0; } }; int main(){ Circle c; //sizeof(Circle)의 크기만큼 메모리를 할당한다음 생성자를 사용하여 메모리에 값을 대입 } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <iostream> using namespace std; class Point{ int _x , _y; public: Point(int x, int y){ _x = x; _y = y; } }; //멤버 이니셜라이저를 반드시 사용해야 하는경우 //1. const 를 선언한 변수 //2. 레퍼런스 변수 - 레퍼런스 변수는 선언과 동시에 반드시 초기화가 되어야 하기 때문ㅇ //3. 기본 생성자가 없는 멤버 데이터가 존재하는 경우 class Circle{ Point p; int _radius; const double PI; public: //Circle() : PI(3.14), p(0,0){ // _radius = 0; //} //위처럼 하거나 아래처럼 하거나 Circle(int x, int y , int r) : PI(3.14), p(x, y), _radius(r){} }; int main(){ Circle c; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | //사용저의 이름과 나이를 저장하는 클래스를 생각해 봅시다. #include <iostream> using namespace std; class Person{ char *name; int age;\ public: //Person(const char* n, int a) : age(a){ // strcpy(name, n); //} Person(string s, int a) : age(a){ name = new char[s.length()]; } void print(){ cout << name << " " << age << endl; } }; //연습문제 : (-> 위의 클래스를 동적할당 하는 코드로 변경하라) int main(){ Person p("hoon", 25); Person q = p; p.print(); q.print(); } | cs |
라고 나는 했는데
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #if 0 //사용저의 이름과 나이를 저장하는 클래스를 생각해 봅시다. #include <iostream> using namespace std; class Person{ char *name; int age; public: //Person(const char* n, int a) : age(a){ // strcpy(name, n); //} Person(const char * n, int a) : age(a){ name = new char[strlen(n)+1]; strcpy(name, n); } ~Person(){ delete[] name; } void print(){ cout << name << " " << age << endl; } }; //연습문제 : (-> 위의 클래스를 동적할당 하는 코드로 변경하라) int main(){ Person p("hoon", 25); Person q = p; p.print(); q.print(); } | cs |
이렇게 하는데 strlen(n)+1 만큼 크기를 잡는데 1은 개행문자 1개이다.
기본 복사 생성자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <iostream> using namespace std; class Person{ char *name; int age; public: Person(const char * n, int a) : age(a){ name = new char[strlen(n) + 1]; strcpy(name, n); } ~Person(){ delete[] name; } void print(){ cout << name << " " << age << endl; } //자신의 타입을 인자로 하는 생성자를 복사 생성자라고 한다. //이는 객체의 복사를 지원하기 위해 사용되는 생성자 //사용자가 복사 생성자를 정의하지 않는경우 , 컴파일러가 이를 자동으로 추가하는데 //이를 기본 복사 생성자라고 한다. //기본 복사 생성자의 복사 정책은 얕은 복사이다. Person(const Person& o) : name(o.name), age(o.age) {} //이건 깊은 복사인가? 아닌가? //Person(const Person& o): name(o.name) , age(o.age) { // name = new char[strlen(o.name) + 1]; // strcpy(name, o.name); // age = o.age; //} }; int main(){ Person p("hoon", 25); Person q = p; // Person q(p) p.print(); q.print(); } | cs |
깊은 복사 생성자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <iostream> using namespace std; class Person{ char *name; int age; public: Person(const char * n, int a) : age(a){ name = new char[strlen(n) + 1]; strcpy(name, n); } ~Person(){ delete[] name; } void print(){ cout << name << " " << age << endl; } //깊은 복사 정책의 복사 생성자 //깊은 복사 얕은 복사 , 참조 계수는 그림 참고 할 것 // 값은 단순 복사하고 동적 할당된 메모리만 깊은 복사를 수행 한다. Person(const Person& o) { name = new char[strlen(o.name) + 1]; strcpy(name, o.name); age = o.age; } }; //만약 객체 내부에서 동적 할당 된 자원이 있다면 반드시 // 소멸자와 복사 생성자를 정의해야 한다. int main(){ Person p("hoon", 25); Person q = p; // Person q(p) p.print(); q.print(); } | cs |
참조 계수 방식 복사 생성자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <iostream> using namespace std; class Person{ char *name; int age; int *ref; public: Person(const char * n, int a) : age(a), ref(new int (1)){ name = new char[strlen(n) + 1]; strcpy(name, n); } //참조 계수 방식의 소멸자 ~Person(){ if (--(*ref) == 0){ delete[] name; delete ref; } } void print(){ cout << name << " " << age << endl; } //참조 계수 방식 복사 생성자 //모드 값을 얕은 복사 후, 참조 계수만 증분한다. 꼭 알둬라 Person(const Person& o) : name(o.name) , age(o.age) , ref (o.ref) { ref++; } }; int main(){ Person p("hoon", 25); Person q = p; // Person q(p) p.print(); q.print(); } | cs |
복사 금지 정책
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <iostream> using namespace std; class Person{ char *name; int age; //복사 금지 정책을 사용하기 위해서는 // Person q = p 같은 코드를 error 내기 위해서는 // 복사 생성자를 private 영역에 정의하면 된다. Person(const Person& o) : name(o.name), age(o.age) { } public: Person(const char * n, int a) : age(a){ name = new char[strlen(n) + 1]; strcpy(name, n); } ~Person(){delete[] name;} void print(){ cout << name << " " << age << endl;} }; int main(){ Person p("hoon", 25); Person q = p; p.print(); q.print(); } | cs |
+) 연습문제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | //연습문제 아래의 동작을 수행하는 클래스를 구현하라 #include <iostream> using namespace std; class String { private: char *name; size_t len; int *ref; public: String(const char * n, int a) : ref(new int(1)){ name = new char[strlen(n) + 1]; strcpy(name, n); } String(const char * n){ name = new char[strlen(n) + 1]; strcpy(name, n); } ~String(){ if (--(*ref) == 0){ delete[] name; delete ref; } } String(const String& o): name(o.name), ref(o.ref){ ++*ref; } char* to_str(){ return name; } }; int main(){ String s1 = "hello"; //String s1("hello") String s2 = s1; //String s2(s1) cout << s1.to_str() << endl; cout << s2.to_str() << endl; //주의할 점 : 반드시 프로세스는 정상종료 해야되며 //복사 정책은 참조 계수 방식으로 } | cs |
'코딩 > 교육' 카테고리의 다른 글
[1219-5] 상수 멤버 함수 / mutable (0) | 2018.12.20 |
---|---|
[1219-4] 유일한 객체를 선언하는 방법 (1) | 2018.12.19 |
[1219-3] 정적 멤버 - 정적 멤버 함수 / 함수 포인터 (0) | 2018.12.19 |
[1219-2] 정적 멤버 - 정적 멤버 변수/ 선언과 정의 (0) | 2018.12.19 |
[1219-1] 정적 멤버 - this와 thiscall (0) | 2018.12.19 |
Comments