ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] CP 07, 08
    C++ 2022. 4. 4. 04:30
    • 객체 포인터와 배열
    #include <iostream>
    using namespace std;
    
    class Line {
    private:
    	int x1, y1;
    	int x2, y2;
    public:
    	int* pX; 
    
    	Line();
    	Line(int _x1, int _y1, int _x2, int _y2);
    	~Line(); //소멸자
    	void print();
    	//setter(accesor) : 데이터는 감추고, 접근할수있는 접근자
    	void setPos1(int _x1, int _y1); //시작점
    	void setPos2(int _x2, int _y2); //끝점
    };
    
    void Line::setPos1(int _x, int _y) {
    	x1 = _x;
    	y1 = _y;
    }
    
    void Line::setPos2(int _x, int _y) {
    	x2 = _x;
    	y2 = _y;
    }
    
    void Line::print() {
    	cout << "[Line] (" << x1 << "," << y1 << ")~(" << x2 << "," << y2 << ")" << endl;
    }
    
    Line::Line() { //생성자는 void X
    	x1 = 0;
    	y1 = 0;
    	x2 = 0;
    	y2 = 0;
    }
    
    Line::Line(int _x1, int _y1, int _x2, int _y2) {
    	x1 = _x1;
    	y1 = _y1;
    	x2 = _x2;
    	y2 = _y2;
    }
    
    Line::~Line() {
    
    }
    
    int main() {
    
    	Line a(1,1,10,10);
    	a.print();
    
    	int ii;
    	//변수 선언 *의 의미 : 이 변수가 포인터 변수이다.
    	int* ip = nullptr; //변수가 만들어지는 순간에 초기화하는게 필수 (특히나 포인터는 실수할 가능성이 높으므로 더욱더 조심), 가르킬 값이 없으면 null pointer라도! (주소값이 없다)
    	ip = &ii; //포인터는 가르키고있는 그 주소에 가는것이 중요함
    
    	//포인터 변수 자체의 *의 의미 : 그 주소에 있는 값을 의미
    	(*ip) = 10; //p라는 포인터변수에 10을 넣는다.
    
    	//포인터에 변수 타입이 따라 붙는 이유 : 주소에 더해서 그 주소에 가면 int가 있다는것까지 표현해야 해서
    
    
    	//class 포인터
    	Line* p = &a;
    	(*p).print(); //괄호를 안치면 다른 의미가 된다. 
    	a.pX = &ii;
    	*a.pX = 10; //우선순위는 *와 . 중에서 .이 더 높으므로 a라는 클래스 변수에 멤버변수로 있는 pX라는 포인터의 값은 10이다 (*을 먼저보지않음), 즉 *(a.pX)로 봄
    
    	//*p.print();는 *(p.print())와 동일. 즉, p라는 포인터자체는 접근해서 값을 열수없음. 주소를 열수있는 건 클래스변수일때만 가능함. print는 함수이므로 함수에는 *을 붙일수없음 (포인터가 아니므로)
    	
    	(*p).print(); //p가 가르키는 값 즉, a에 가면 print()라는 함수가있다.
    
    	//같은의미임
    	a.print(); //그냥 변수일경우에는.을 사용
    	p->print(); //p라는 포인터에 가서 열면 print라는 함수가있다.
    
    	Line arr[10]; //배열을 만들면 기본생성자가 호출됨. (따로 지정하지않는다면) 즉, 배열을 만들땐 기본생성자가 없으면 만들수가없음.
    	
    	//각각 만들수도 있음
    	Line arr1[3] = { Line(3, 4, 5, 6), Line(1,1,1,1),Line(2, 5, 2,6) };
    	for (int i = 0; i < 3; i++)
    		arr[i].print();
    
    	//2차원 배열 초기화 (뒤에서부터봄)
    	Line arr2[2][3] = { { Line(3, 4, 5, 6), Line(1,1,1,1),Line(2, 5, 2,6) }, { Line(1,1,1,1), Line(2,2,2,2),Line(3,3,3,3) } };
    	for (int i = 0; i < 2; i++) {
    		for (int j = 0; j < 3; j++) {
    			arr2[i][j].print();
    		}
    		cout << "=======================" << endl;
    	}
    		
    	for (int i = 0; i < 10; i++) {
    		arr[i].setPos1(i, i);
    		arr[i].setPos2(3 * i, 4 * 1);
    	}
    	for (int i = 0; i < 10; i++)
    		arr[i].print();
    
    
    	//배열은 포인터로 접근 가능
    	Line* q = &(arr2[1][0]); //arr[0][0]
    	for (int i = 0; i < 3; i++) { //i<6 이렇게 순차적으로 해도 상관없음
    		q[i].print();
    	}
    
    	return 0;
    }
    • 동적 메모리 1-1
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    class Line {
    private:
    	int x1, y1;
    	int x2, y2;
    public:
    	Line();
    	Line(int _x1, int _y1, int _x2, int _y2);
    	~Line(); //소멸자
    	void print();
    	//setter(accesor) : 데이터는 감추고, 접근할수있는 접근자
    	void setPos1(int _x1, int _y1); //시작점
    	void setPos2(int _x2, int _y2); //끝점
    };
    
    void Line::setPos1(int _x, int _y) {
    	x1 = _x;
    	y1 = _y;
    }
    
    void Line::setPos2(int _x, int _y) {
    	x2 = _x;
    	y2 = _y;
    }
    
    void Line::print() {
    	cout << "[Line] (" << x1 << "," << y1 << ")~(" << x2 << "," << y2 << ")" << endl;
    }
    
    Line::Line() { //생성자는 void X
    	x1 = 0;
    	y1 = 0;
    	x2 = 0;
    	y2 = 0;
    }
    
    Line::Line(int _x1, int _y1, int _x2, int _y2) {
    	x1 = _x1;
    	y1 = _y1;
    	x2 = _x2;
    	y2 = _y2;
    }
    
    Line::~Line() {
    
    }
    
    int main() {
    
    	//C
    	/*int* darr1 = (int*)malloc(sizeof(int) * 10); //10개의 배열 만들기, int형 포인터로 사용
    	Line* darr2 = (Line*)malloc(sizeof(Line) * 10); //생성자랑 전혀 상관없음
    
    	free(darr1);
    	free(darr2);*/
    
    	//C++
    	int* darr1 = new int[10]; //int 10개를 만들어서 줄것이다라는 의미
    	Line* darr2 = new Line[10];
    	Line* dp = new Line(2, 3, 4, 5); //하나를 만든다는 의미
    
    	delete[] darr1;
    	delete[] darr2;
    	delete dp;
    	dp = nullptr; //delete를 지우고 항상 초기화해주기! (메모리를 가르치지않는 포인트는 무시해버리기때문)
    	delete dp; //nullptr로 초기화하지않으면, 두번 지울수없음.
    
    	//기본생성자가 없을때 초기화하는 방법 (장점-내가원하는 생성자를 각각의 원소를통해 만들수있다, 단점-정적배열이다.)
    	Line* darr4[10]; //포인터를 10개를 만든다는 것
    	//Line* darr4[size]; //정적배열이므로 이렇게 지정할수없다.
    
    	for (int i = 0; i < 10; i++) {
    		darr4[i] = new Line(2, 2, 3*i, 4*i);
    	}
    
    	for (int i = 0; i < 10; i++) {
    		darr4[i]->print(); //포인터의 멤버함수를 호출한다.
    	}
    
    	for (int i = 0; i < 10; i++) {
    		delete darr4[i];
    	}
    
    	//개수를 동적으로 받고싶다면? 포인터의 배열을 만드는것을 동적으로 하면된다.
    	int size = 100;
    	//Line* darr5[size]; 
    	
    	//기존 동적배열 방식에서 int 자리에 Line*를 집어넣으면됨.
    	/*int a[10];
    	int *a = new int[10];*/
    	Line** darr5 = new Line * [size]; //포인터의 배열 사이즈가 생겨나는것. (포인터의 배열을 동적으로 n개 만드는것-더블포인터), 포인터배열로 만들었기때문에 서로다른 위치의 메모리를 참조하게됨.
    
    	//각각의 원소 생성
    	for (int i = 0; i < size; i++) {
    		darr5[i] = new Line(2, 2, 3 * i, 4 * i);
    	}
    
    	for (int i = 0; i < size; i++) {
    		darr5[i]->print(); //포인터의 멤버함수를 호출한다.
    	}
    
    	//각각의 원소 지우기
    	for (int i = 0; i < size; i++) {
    		delete darr5[i];
    	}
    
    	//배열 이름 자체도 지워줘야함. (전체배열 지우기)
    	delete [] darr5;
    
    	return 0;
    }
    • this 포인터 (클래스 속에서 자기자신을 가리킴)
    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    
    class Line {
    private:
    	int x1, y1;
    	int x2, y2;
    public:
    	Line();
    	Line(int _x1, int _y1, int _x2, int _y2);
    	~Line(); //소멸자
    	void print();
    	//setter(accesor) : 데이터는 감추고, 접근할수있는 접근자
    	void setPos1(int _x1, int _y1); //시작점
    	void setPos2(int _x2, int _y2); //끝점
    	float getLength() { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } //선분의 길이, sqrt() : math함수(제곱함수)
    	bool isLong(Line* in); //in이랑 비교해서 내가 크면 true, 아니면 false
    };
    
    void Line::setPos1(int _x, int _y) {
    	x1 = _x;
    	y1 = _y;
    }
    
    void Line::setPos2(int _x, int _y) {
    	x2 = _x;
    	y2 = _y;
    }
    
    void Line::print() {
    	this->x1;
    	cout << "[Line] (" << x1 << "," << y1 << ")~(" << x2 << "," << y2 << ")" << endl;
    }
    
    Line::Line() { //생성자는 void X
    	x1 = 0;
    	y1 = 0;
    	x2 = 0;
    	y2 = 0;
    }
    
    Line::Line(int _x1, int _y1, int _x2, int _y2) {
    	x1 = _x1;
    	y1 = _y1;
    	x2 = _x2;
    	y2 = _y2;
    }
    
    Line::~Line() {
    
    }
    
    //전역함수 (a와 b의 길이중 어느것이 더긴지 비교)
    bool compare(Line *a, Line *b) { //class를 인자로 받을때는 용량이 커서 포인터로 받는다.
    	if (a->getLength() > b->getLength())
    		return true;
    	return false;
    }
    
    bool Line::isLong(Line* in) { //멤버함수
    	//코드를 중복해서 짜지않고
    	/*if (getLength() > in->getLength())
    		return true;
    	return false;*/
    
    	//compare 함수 이용
    	if (compare(this, in) == true) //this : 나, 멤버함수에서 자기자신을 넘겨줄때 this를 사용
    		return true;
    	return false;
    
    	//return compare(this, in);과 같은 의미
    }
    
    int main() {
    
    
    	return 0;
    }
    • 동적 메모리 1-2
    #include <iostream>
    using namespace std;
    
    
    
    int main() {
    	//int* arr = new int[10];  : int*가 배열을 하나 만드는것
    	//int * [] : 포인터의 배열을 만들면 2차원 배열을 만들수있음.
    
    	//int arr[10][5]와 갯수는 같지만, 메모리 구조는 완전히 다름.
    	//int arr[10][5] : 5개씩 10묶음 있는것 (int 50개가 한줄로 쭉 만들어지는것, 각각 5묶음으로 생각하는것) -1차원배열과 호환됨
    	int* arr[10]; //int*의 배열
    	for (int i = 0; i < 10; i++) { //배열이있는데, 각각의 배열이 포인터임. 포인터가 5개씩 있는 원소를 가리킴. (5개씩 파편화되어있음) 
    		arr[i] = new int[5];
    	}
    
    	for (int i = 0; i < 10; i++) {
    		delete[] arr[i];
    	}
    
    
    	return 0;
    }
    • 동적 메모리 1-3 (2차원 배열 동적할당)
    #include <iostream>
    using namespace std;
    
    void func1(int arr[][5]) { //함수의 인자를 배열로 받기
    	arr[1][3]; //5개씩 묶음을 한번 건너띄고 3번 건너띄고 시작되는값.
    }
    
    void func2(int** arr) {
    	arr[1][3]; //두번째 포인터가 의미하는 주소에 가서 3번째 있는값을 읽어라.
    }
    int main() {
    	int n = 10;
    	int m = 5;
    	int brr[10][5];
    	func1(brr); //메모리구조상 1차원배열처럼 일렬로 되어있어서 가능.
    
    	//int arr[n][m];
    
    	int** arr = new int *[n]; //포인터의 배열을 동적으로 만들어주어야함(new로 만든것은 n개의 포인터)
    	for (int i = 0; i < n; i++) { 
    		arr[i] = new int[m];
    	}
    
    	//func1(arr); //메모리구조상 파편화되어있어서 받을 수 없음.
    	func2(arr);
    
    	for (int i = 0; i < n; i++) {
    		delete[] arr[i];
    	}
    
    	delete[] arr;
    
    	return 0;
    }
    • String 1-1
    #include <iostream>
    #include <string>
    using namespace std;
    
    void func(char *str) { //문자열을 인자로 받는 함수
    	str[0] = 'S';
    }
    
    void func1(const char* str) { //char에 포인터를 받을건데, 그 값을 변경시키지않을거야 (포인터가 가르키고있는 값을 변경하지않을것이다)
    	//str[0] = 'S'; 바꾸려는 시도는 에러가남.
    	char c = str[0]; //값을 읽으려는 시도는 괜찮음.
    	c = 'S'; //읽은다음에 바꾸는건 상관없음. 자체를 바꾸는것이 나이므로
    }
    
    int main() {
    	string a("sejong university"); //문자열의 literal로 입력받는 함수는 const char*로 만들어야 받을수있음.
    	cout << a << endl;
    
    	//func("software")와 func(text)의 차이
    	char text[] = "software"; //(프로그램 실행 내내 변하지않음) literal이므로 컴파일링할때 이미 정해져있어서 변하지않음.
    	text[0] = 'S'; //배열을 만들어서 주게되면 복사본이 만들어지는것임. software라는 문자열은 사라지지않고 복사본의 값을 변화시키는것임.
    	func(text);
    	//func("software"); //변경시킬수 없는 곳에 있는 메모리에 직접주는것임. literal에 직접 주는것은 막혀있다.
    	func1("software");
    
    	return 0;
    }
    • String 1-2 (포인터)
    #include <iostream>
    #include <string>
    using namespace std;
    
    void func(char* str) { //문자열을 인자로 받는 함수
    	str[0] = 'S';
    }
    
    void func1(const char* str) { //char에 포인터를 받을건데, 그 값을 변경시키지않을거야 (포인터가 가르키고있는 값을 변경하지않을것이다)
    	//str[0] = 'S'; 바꾸려는 시도는 에러가남.
    	char c = str[0]; //값을 읽으려는 시도는 괜찮음.
    	c = 'S'; //읽은다음에 바꾸는건 상관없음. 자체를 바꾸는것이 나이므로
    }
    
    void func2(int* p) {
    	*p = 10; //p가 가르키는 곳으로가서 그 값을 주겠다.
    }
    
    int func5() {
    	int a = 10;
    	return a;
    }
    
    int *func6() { //함수자체를 잘못만든것 (함수는 main메모리 위에 stack메모리에 생기는데, 주소를 main에 넘겨주면 본인 메모리가 사라짐), a의 주소는 사라진 주소이므로 그 주소로 가서 아무것도 할수없음.
    	int a = 10;
    	return &a;
    }
    
    int* func7() { //이건 가능 (main에서 함수를 부르면 new로 만들면 heap메모리에 생김 (동적메모리), 포인터는 heap메모리에 있는걸 가르키므로 본인 함수 메모리(stack)이 사라져도 접근가능)
    	int *a = new int; //포인터로 넘겨주려면 동적으로 만들어야한다.
    	*a = 10; 
    	return a;
    }
    
    class Circle {
    public:
    	Circle() {
    		x = 0;
    		y = 0;
    		r = 1;
    	}
    	Circle(int _x, int _y, int _r) {
    		x = _x;
    		y = _y;
    		r = _r;
    	}
    	int x, y, r;
    	void print() {
    		cout << "[CIRCLE] (" << x << ","<< y << ") r=" << r << endl;
    	}
    };
    
    int main() {
    	string a("sejong university"); //문자열의 literal로 입력받는 함수는 const char*로 만들어야 받을수있음.
    	cout << a << endl;
    
    	//func("software")와 func(text)의 차이
    	char text[] = "software"; //(프로그램 실행 내내 변하지않음) literal이므로 컴파일링할때 이미 정해져있어서 변하지않음.
    	text[0] = 'S'; //배열을 만들어서 주게되면 복사본이 만들어지는것임. software라는 문자열은 사라지지않고 복사본의 값을 변화시키는것임.
    	func(text);
    	//func("software"); //변경시킬수 없는 곳에 있는 메모리에 직접주는것임. literal에 직접 주는것은 막혀있다.
    	func1("software");
    
    	int i;
    	func2(&i); //이렇게 불러도 전혀 문제없음
    
    	//func2(&(20))//절대 안댐 (literal의 주소는 넘길수없음)
    
    	i = func5(); //a를 만들고 return 10을 함
    	int* p = &i; //이건 가능
    	//int* p; //이 포인터는 아무것도 가리키지않으므로 
    	*p = func5(); //이건 안댐. (값을 줄수없음)
    	p = func6(); //이것도 안됨.
    
    	Circle c;
    	c.print();
    
    	Circle c1(10, 20, 30);
    	c1.print();
    	
    
    	return 0;
    }
    • 값에 의한 호출로 객체 전달
    #include <iostream>
    #include <string>
    using namespace std;
    
    void func(char* str) { //문자열을 인자로 받는 함수
    	str[0] = 'S';
    }
    
    void func1(const char* str) { //char에 포인터를 받을건데, 그 값을 변경시키지않을거야 (포인터가 가르키고있는 값을 변경하지않을것이다)
    	//str[0] = 'S'; 바꾸려는 시도는 에러가남.
    	char c = str[0]; //값을 읽으려는 시도는 괜찮음.
    	c = 'S'; //읽은다음에 바꾸는건 상관없음. 자체를 바꾸는것이 나이므로
    }
    
    void func2(int* p) {
    	*p = 10; //p가 가르키는 곳으로가서 그 값을 주겠다.
    }
    
    int func5() {
    	int a = 10;
    	return a;
    }
    
    int *func6() { //함수자체를 잘못만든것 (함수는 main메모리 위에 stack메모리에 생기는데, 주소를 main에 넘겨주면 본인 메모리가 사라짐), a의 주소는 사라진 주소이므로 그 주소로 가서 아무것도 할수없음.
    	int a = 10;
    	return &a;
    }
    
    
    
    class Circle {
    public:
    	Circle() {
    		cout << "기본 생성자 호출" << endl;
    		x = 0;
    		y = 0;
    		r = 1;
    	}
    	Circle(int _x, int _y, int _r) {
    		cout << "인자 있는 생성자 호출" << endl;
    		x = _x;
    		y = _y;
    		r = _r;
    	}
    	int x, y, r;
    	void print() {
    		cout << "[CIRCLE] (" << x << ","<< y << ") r=" << r << endl;
    	}
    };
    
    void func7(Circle d)
    {
    	d.print();
    }
    
    int main() {
    	string a("sejong university"); //문자열의 literal로 입력받는 함수는 const char*로 만들어야 받을수있음.
    	cout << a << endl;
    
    	//func("software")와 func(text)의 차이
    	char text[] = "software"; //(프로그램 실행 내내 변하지않음) literal이므로 컴파일링할때 이미 정해져있어서 변하지않음.
    	text[0] = 'S'; //배열을 만들어서 주게되면 복사본이 만들어지는것임. software라는 문자열은 사라지지않고 복사본의 값을 변화시키는것임.
    	func(text);
    	//func("software"); //변경시킬수 없는 곳에 있는 메모리에 직접주는것임. literal에 직접 주는것은 막혀있다.
    	func1("software");
    
    	int i;
    	func2(&i); //이렇게 불러도 전혀 문제없음
    
    	//func2(&(20))//절대 안댐 (literal의 주소는 넘길수없음)
    
    	i = func5(); //a를 만들고 return 10을 함
    	int* p = &i; //이건 가능
    	//int* p; //이 포인터는 아무것도 가리키지않으므로 
    	*p = func5(); //이건 안댐. (값을 줄수없음)
    	p = func6(); //이것도 안됨.
    
    	Circle c(10, 20, 30); //컴퓨터는 내용값이 궁금하지않음
    	c.print();
    	func7(c); //in func7 stack memory, Circle d=c; 이 메모리는 초기값이 뭔지안다. (c에서 그대로 가져올것이므로) - 따라서 생성자가 굳이 불리지않음 (기본생성자가 호출되지않음)
    	//1
    	Circle e = c; //copy (그냥 12바이트를 그대로 복사함) - 기본생성자가 호출되지않음
    	//2
    	Circle e; //이럴때는 기본생성자가 한번 더 불림
    	e = c;
    	//1과 2는 다르다. why? 1은 copy (기본생성자가 호출되지않음) 2는 기본생성자가 한번 더 불림
    
    	c.x = 1000; //copy or clone이 일어난것 (복사본이 생긴것)
    	c.print(); //c랑 e는 메모리 공유하지않음.
    	e.print();
    
    	cout << sizeof(Circle) << endl;
    
    	return 0;
    }
    • 참조
    #include <iostream>
    #include <string>
    using namespace std;
    class Circle {
    public:
    	Circle() {
    		cout << "기본 생성자 호출" << endl;
    		x = 0;
    		y = 0;
    		r = 1;
    	}
    	Circle(int _x, int _y, int _r) {
    		cout << "인자 있는 생성자 호출" << endl;
    		x = _x;
    		y = _y;
    		r = _r;
    	}
    	int x, y, r;
    	void print() {
    		cout << "[CIRCLE] (" << x << "," << y << ") r=" << r << endl;
    	}
    };
    
    void func7(Circle d)
    {
    	d.print();
    }
    
    void func8(Circle f) {
    	f.r = 300;
    	return;
    }
    
    void func9(Circle& f) { //아까있던 c와같은놈 (한번 별명을 만들면 죽을때까지 이놈임)
    	f.r = 300; //이 메모리는 언제나 존재 (지울일도 건들일일도 없기때문에)
    	f.print();
    	return;
    }
    
    //func9와 같은 코드
    void func10(Circle* p) { //* : 변수선언하면서 만들면 포인터라는 의미 //아까있던 c의 주소
    	//1
    	//(*p).r = 300; //포인터앞에 *이 있으면 그 포인터가 가리키는 값이 된다.
    	//2
    	p->r = 300;
    	p->print();
    	//1과 2는 같은것임
    
    	////이거같은 경우
    	//Circle d;
    	//p = &d;
    	//p->r = 300; 
    	////이렇게 해버리면 중간에 p의 의미가 바껴버림 (주는건 c의 주소였는데, d의 주소로 존재하는 d를 바꿈)
    
    	//포인터는 이 메모리가 유효한지 항상 확인해줘야함
    	//ex) delete p;
    	//	  p->r=300;
    	//이미 없는 주소이므로 접근불가능 (하지만 레퍼런스는 다름)
    	return;
    }
    
    void mySwap(int& a, int& b) //별명끼리 값을 바꾸는것
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    
    //레퍼런스 변수를 통해 값을 리턴하는것도 가능
    int  func10() {
    	int a = 10;
    	return a;
    }
    
    int & func11() {//이건 불가능 (return받는애한테 a의 별명을 주는것임)
    	int a = 10;
    	return a;
    }
    
    int gAAA = 30;
    int& func12() { //이건 또 가능,,, (함수 리턴을 통해 다른놈 전달 가능)
    	return gAAA;
    }
    
    int gArr[10];
    int& func13(int ind) {
    	////조건을 맞춰서 문제없이 만들수있음.
    	//if(ind < 0) ind = 0;
    	//if(ind > 10) ind = 9;
    	//종료조건도 심어놓을수있음 (이것저것의 예시)
    	if (ind < 0 || ind >= 10) { 
    		cout << "Error!!!! - Out of Bound of gArr" << endl;
    		exit(-1);
    	}
    	return gArr[ind];
    }
    
    int main() {
    	Circle c(10, 20, 30); //컴퓨터는 내용값이 궁금하지않음
    	c.print();
    	func7(c); //in func7 stack memory, Circle d=c; 이 메모리는 초기값이 뭔지안다. (c에서 그대로 가져올것이므로) - 따라서 생성자가 굳이 불리지않음 (기본생성자가 호출되지않음)
    	////1
    	//Circle e = c; //copy (그냥 12바이트를 그대로 복사함) - 기본생성자가 호출되지않음
    	////2
    	//Circle e; //이럴때는 기본생성자가 한번 더 불림
    	//e = c;
    	//1과 2는 다르다. why? 1은 copy (기본생성자가 호출되지않음) 2는 기본생성자가 한번 더 불림
    
    	c.x = 1000; //copy or clone이 일어난것 (복사본이 생긴것)
    	c.print(); //c랑 e는 메모리 공유하지않음.
    	//e.print();
    
    	cout << sizeof(Circle) << endl;
    
    	//참조는 이런식으로 사용하지않음 
    	int aa = 10;
    	int& r = aa; //참조는 단독으로 만들수없음 (기존(aa)의 별명이므로)
    	r = 20; //aa의 값도 바뀜 
    	cout << "a=" << aa << ", r=" << r << endl;
    
    	int bb = 30;
    	r = bb; //r은 언제나 a와 같은놈, 값에 복사가 일어나므로 bb의 값이 r로 가는거지, bb의 원래값은 변하지않음.
    	r = 40;
    	cout << "bb=" << bb << ", r=" << r << endl; //bb는 바뀌지 않음, r만 바뀜
    
    	Circle& rr = c; //c와 똑같은 rr이 만들어짐 (c를 rr로 지칭)
    	rr.print();
    
    	//참조 사용은 이런식으로
    	func8(c);
    	c.print();
    
    	func9(c);
    	c.print();
    
    	func10(&c); //& : 변수 선언시 쓰면 레퍼런스 변수를 만든다는 의미, 존재하는 변수앞에 있으면 그놈의 주소라는 의미
    	c.print();
    
    	//레퍼런수 변수의 존재의미는 포인터를 대체하는용 
    	//장점 : 주소가 감춰짐 
    
    
    	int aaa = 30;
    	int bbb = 100;
    	mySwap(aaa, bbb);
    	cout << "aaa= " << aaa << ", bbb=" << bbb << endl;
    
    	int ccc = func10();
    	cout << "ccc=" << ccc << endl;
    
    	int & ccc1 = func11(); //func11을 통해 a의 별명을 main에 주는데, ccc는 a와 같은데, func11은 더이상 존재하지 않고 사라지므로 본체가 사라지고 별명만 남아서 이상한값이 들어가게되는것 
    	cout << "ccc1=" << ccc1 << endl;
    
    	int& ccc2 = func12(); //(ccc2와 gAAA는 동체이다)
    	ccc2 = 50;
    	cout << "gAAA=" << gAAA << endl; //gAAA의 값
    
    	func12() = 100; //이게 가능해짐, 리턴값이 gAAA자체이기때문에
    	cout << "gAAA=" << gAAA << endl; //gAAA의 값
    
    	//배열을 접근하는 또 다른 방식 : 장점 - 함수이므로 이것저것 할수있음
    	for (int i = 0; i < 10; i++)  //func13()이 i번째 배열 그 자체와 같음
    		func13(i) = i * 10; //함수는 i를 받아서 gArr[i]번째 값(레퍼런스)을 리턴함
    	
    	for(int i=0;i<10;i++)
    		cout << "gArr[" << i << "]=" << gArr[i] << endl; //배열값 자체이므로 아무것도할수없음
    	
    	gArr[11] = 20; //아무문제없음
    	func13(11) = 20; //에러메시지가 나옴 (문제가 생긴걸 알수있음) - 값의 유효성을 알수있어서 안전함
    
    	//함수의 인자로 값을 변화시킬때 사용, 리턴값으로 그놈자체를 지칭할때 씀 (배열의 인덱스 접근을 수단으로써 사용가능)
    	
    	return 0;
    }

     

    'C++' 카테고리의 다른 글

    [C++] CP 13  (0) 2022.04.17
    [C++] CP 11, 12  (0) 2022.04.17
    [C++] CP 09, 10  (0) 2022.04.14
    [C++] CP 05, 06  (0) 2022.03.29
    [C++] CP 01, 02, 03, 04  (0) 2022.03.12
Designed by Tistory.