Jam's story

[C++] 함수의 참조, 복사 생성자 본문

2021-2학기/C++

[C++] 함수의 참조, 복사 생성자

애플쩀 2021. 10. 10. 14:52

이해가 어려워서 계속 반복중인 파트... 다시 정리하면서 공부하자 !!!! 

함수의 참조

값에 의한 호출 ->원본의 값을 훼손하지 않는다.

주소에 의한 호출 -> 원본의 값도 바뀜

주소에 의한 호출

void increse(Circle *p){ //내용 } int main(){ Circle c(30); increase(&c); }

참조변수

 

원본객체에 연산이 됨 =원본이 변형된다는 말  생성자 , 소멸자 모두 실행되지 않는다 

int &refn= n ; -> refn은 n의 별명, refn의 값을 바꾸면 n의 값도 같이 바꿔짐 둘은 동일한 변수

 

Circle &c=circle

참조변수는 초기화로 지정된 원본 변수의 공간을 공유한다.

참조변수에 대한 포인터도 만들수 있다.

int *p=&refn; *p=20;

 

참조변수 선언시 주의사항

-초기화가 없다면 컴파일 오류

-참조자 &의 위치는 무관 변수타입이랑 변수명 사이에 오기만 하면됨

-참조변수의 배열을 만들수 없다.-참조변수에 대한 참조선언이 가능하다 int &r=refn;

 

 

char c = 'a';
char* p = &c; //p는 c의 주소를 가짐 
*p = 'b'; //*p=c
cout << *p<<' '<<c<<endl; //c='b'
char& an = c; //an는 c의 별명 
an = 'c';
cout << an<< ' '<<c; //an=c;

 

얕은복사와 깊은 복사

깊은 복사는 얕은 복사와 달리 메모리도 복사되어있기때문에, 원본가 사본의 변수는 서로 다른 메모리를 가리킨다.

얕은복사는 메모리까지는 복사되지 않았기에 , 원본과 사본이 같은 메모리를 가르킨다. 즉 사본의 값을 변경하면 원본도 변경된다는 뜻이다.

복사생성자 생성class ClassName{ ClassNmae(ConstName& c) };class Circle{ Circle(int r); Circle(const Circle& c); }; int main(){ Circle src(30); Circle dest(src); }복사생성자의 규칙

*복사생성자는 클래스에 오직 한개만 선언할 수 있다.

*자기 클래스에 대한 참조로 선언된다.

*매개변수는 오직하나이다.

 

깊은 복사생성자 구현

 

Person:: Person(const Person& p) 처럼 자기 자신클래스의 참조를 만들어준다 

p(객체의) . name  혹은 .id 로 접긎ㄴ

char *name 이기 때문에, name에 new char[길이+널문자]; 배열 선언 

그 배열에 char을 넣어줘야하니, for문이나 strcpy를 사용

 strcpy(a,b) b를 a에 복사시키는것 

Person::Person(const Person& person) {//복사생성자
	this->id = person.id;
	int len = strlen(person.name);
	this->name = new char[len + 1];
	strcpy(this->name, person.name);
	cout << "복사생성자 실행  ,원본객체의 이름 " << this->name << endl;
}


Person::Person(int id, const char* name) { // 생성자
	this->id = id;
	int len = strlen(name); // name의 문자 개수
	this->name = new char[len + 1]; // name 문자열 공간 핟당
	strcpy(this->name, name); // name에 문자열 복사
}

실습문제 다시풀기 

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class Circle {
public:
	void swap(int &a,int &b);
};
void Circle::swap(int& a, int& b) {
	int tmp;
	tmp = a;
	a = b;
	b = a;
	
}
int main() {
	int m = 2; 
	int n = 9;
	swap(m, n);
	cout << m << ' ' << n;
}

2번

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
void half(double& su) {
	su /= 2;

}
int main() {
	double n = 20;
	half(n);
	cout << n;
}

3번

s3에만 참조를 줘도 된다 

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
void combine(string s1, string s2, string& s3) {
	s3 = s1 + " " + s2;
}
int main() {
	string text1("i love you"), text2("very much");
	string text3;
	combine(text1, text2, text3);
	cout << text3;
}

4번

 

이거 왜 결과가 숫자가 제대로 안나오는지 모르겠다. .-> 해결 

else { big = b; }
    return false; 
} 이부분에서 return false 를 먼저써서 

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
bool bigger(int a, int b, int& big){
	if (a == b) { return true; }
	else { 
		
	if (a > b) { big = a; }
	else { big = b; }
    return false; 
	}
	}
int main() {
	int a, b, big;

	a = 5; b = 10;
	if (bigger(a, b, big)) {
		cout << "두 수는 같습니다" << endl;
	}
	else {
		cout << a << "와 " << b << "중 큰 수는 " << big << "입니다." << endl;
	}

	return 0;
}

5번

#include <iostream>
#include <string>

using namespace std;

class Circle {
	int radius;
public:
	Circle(int r) { radius = r; }
	int getRadius() { return radius; }
	void setRadius(int r) { radius = r; }
	void show() { cout << "반지름이 " << radius << "인 원" << endl; }
};

void increaseBy(Circle& a, Circle b) {
	int r = a.getRadius() + b.getRadius();
	a.setRadius(r);
}

int main() {
	Circle x(10), y(5);
	increaseBy(x, y);
	x.show();
	return 0;
}

6번

#include <iostream>
#include <string>

using namespace std;

char& find(char a[], char c, bool& success){

	for (int i = 0; i < strlen(a); i++) {
		if (a[i] == c) {
			success = true;
			return a[i];
		}
		else {
			success = false;
		}
	}
}
int main() {
	char s[] = "Mike";
	bool b = false;
	char& loc = find(s, 'M', b);
	if (b == false) {
		cout << "M을 발견할 수 없다 " << endl;
		return 0;
	}
	loc = 'm';
	cout << s << endl;
	return 0;
}

7번

 

이건 다시봐도 문제가 어렵다... pop 팝하여 n개에 저장 .. 이게 뭔소랴.

#include <iostream>
#include <string>

using namespace std;

class MyIntStack {
	int p[10];
	int tos;
public:
	MyIntStack() { tos = -1; }
	bool push(int n);
	bool pop(int& n);
};
bool MyIntStack::push(int n) {
	if (tos >= 9) return false;
	p[++tos] = n;
	return true;
}
bool MyIntStack::pop(int& n) {
	if (tos < 0) return false;
	n = p[tos--];
	return true;
}
int main() {
	MyIntStack a;
	for (int i = 0; i < 11; i++) {
		if (a.push(i)) cout << i << ' ';
		else cout << endl << i + 1 << " 번째 stack full" << endl;
	}
	int n;
	for (int i = 0; i < 11; i++) {
		if (a.pop(n)) cout << n << ' ';
		else cout << endl << i + 1 << " 번째 stack empty";
	}
	cout << endl;

	return 0;
}

8번

#include <iostream>
#include <string>

using namespace std;

class MyIntStack {
	int* p;
	int size;
	int tos;
public:
	MyIntStack():MyIntStack(1){}
	MyIntStack(int size);
	MyIntStack(const MyIntStack& s);
	~MyIntStack() { delete[] p; }
	bool push(int n);
	bool pop(int& n);
};
MyIntStack::MyIntStack(int size) {
	this->p = new int[size];
	this->size = size;
	this->tos = -1;
}
MyIntStack::MyIntStack(const MyIntStack& s) {
	p = new int[s.size];
	this->size = s.size;
	this->tos = s.tos;
	for (int i = 0; i < s.size; i++) {
		this->p[i] = s.p[i];
	}
}
bool MyIntStack::push(int n) {
	if (tos >= 9) return false;
	p[++tos] = n;
	return true;
}
bool MyIntStack::pop(int& n) {
	if (tos < 0) return false;
	n = p[tos--];
	return true;
}
int main() {
	MyIntStack a(10);
	a.push(10);
	a.push(20);
	MyIntStack b = a;
	b.push(30);

	int n;
	a.pop(n);
	cout << "스택 a에서 팝한 값 " << n << endl;

	b.pop(n);
	cout << "스택 b에서 팝한 값 " << n << endl;

	return 0;
}

9번

틀렸었던 이유-> retrun *this. 

acc.add(5).add(6) 이부분을 보면 객체 자신 this가 아닌 *this로 해야한다. 

#include <iostream>
#include <string>

using namespace std;
class Accumulator {
	int value;
public:
	Accumulator(int value);
	Accumulator& add(int n);
	int get();
};
Accumulator::Accumulator(int value) {
	this->value = value;
}
Accumulator& Accumulator:: add(int n){
	this->value += n;
	return *this;
}
int  Accumulator::get() {
	return value;
}
int main() {
	
	Accumulator acc(10);
	acc.add(5).add(6).add(7);
	cout << acc.get();
	return 0;
}

10번

틀린이유-> 

1. Buffer& append 함수는 Buffer 클래스 밖에 선언해야한다 

2. 매개변수에서 (Buffer b 와 Buffer& b는 결과가 다르다 

Buffer b라고 하면, 원본의 값이 바뀌지 않기때문에 main함수에서 호출했을시에 값이 원본으로 출력한다 

Buffer& b라고 하면 원본값이 바뀌기 때문에 string이 추가된 것이 반환된다 

#include <iostream>
#include <string>

using namespace std;
class Buffer {
	string text;
public:
	Buffer(string text) { this->text = text; }
	
	void add(string next) { text += next; }
	void print() { cout << text << endl; }
};
Buffer&  append(Buffer& b, string s) {
	b.add(s);
	return b;
}
int main() {
	Buffer buf("Hello");
	Buffer& temp = append(buf, "Guys");
	temp.print();
	buf.print();
	return 0;
}

11번

string을 쓰면 메모리 할당받을 필요가 없다. (char *title 과 비교)

#include <iostream>
#include <string>

using namespace std;
class Book {
	string title;
	int price;
public:
	Book(string  title, int price);
	Book(Book& b);
	~Book() {  }
	void set(string title, int price);
	void show() { cout << title << ' ' << price << "원" << endl; }
};
Book::Book(string title, int price) {
	this->title = title;
	this->price = price;
}
void Book::set(string title, int price) {
	this->title = title;
	this->price = price;
}
Book::Book(Book& b) {
	this->title = b.title;
	this->price = b.price;
}
int main() {
	Book cpp("명품C++", 10000);
	Book java = cpp;
	java.set("명품자바", 12000);
	cpp.show();
	java.show();

	return 0;
}

12번 안틀리고 성공!! 

#include <iostream>
#include <cstring>

using namespace std;

class Dept {
	int size;
	int* scores;
public:
	Dept(int size) { this->size = size; scores = new int[size]; }
	Dept(const Dept& dept);
	~Dept(){}
	int getSize() { return size; }
	void read();
	bool isOver60(int index);
};
Dept::Dept(const Dept& dept) {
	this->size = dept.size;
	scores = new int[dept.size];
}
void Dept::read() {
	cout << size << "개의 점수 입력";
	for (int i = 0; i < size; i++) {
		cin >> scores[i];
	}
}
int countPass(Dept& dept) {
	int count = 0;
	for (int i = 0; i < dept.getSize(); i++) {
		if (dept.isOver60(i)) count++;
	}
	return count;
}
bool Dept:: isOver60(int index) {
	if (scores[index] > 60)return true;
	else return false;
}
int main() {
	Dept com(10);
	com.read();
	int n = countPass(com);
	cout << "60점 이상은" << n;
}

'2021-2학기 > C++' 카테고리의 다른 글

c++기본  (0) 2021.10.26
c4996 에러 해결방법  (0) 2021.10.24
2장 틀렸던 문제 다시풀어보기  (0) 2021.10.24
[명품 c++ programming] 5장 open challenge  (0) 2021.10.10
[C++ programming ] 실습문제 6장  (0) 2021.10.08
Comments