C++/명품 C++ Programming

[8]명품 C++ Programming -5장[ 함수와 참조, 복사 생성자](1)-[내용정리]

Tomato_Coffee 2022. 6. 5. 18:16
  • 1.


함수에 대해 알아보자

함수는 1.변수를 직접주는 방식, 2.다른 방법은 포인터에의한 호출
1. call by value
2. call by address

 

  • 2.

func4(&i) // 문제 없음 변수의 주소는 줄수있지만
func4(&(20))// 안됨//리터럴의 주소는 줄수없음---> 줄수있다면 값을 바꿔버릴수있기 때문에

 

  • 3

어떤 함수에 인자로 주게 되면 , 즉 호출하게 되면 func7(c)---> void func7(Circle d=c)이런식으로 이해해야함
여기에서 '=' : 할당 연산자 라고 불린다.(assignment) 사실은 copy(clone)라고 부른다.---> assignment(값을준다)랑copy는 완전히 다른것이다. 다음에 알려드림
// 47m
1. Circle e= c; and func7(c);// 이때 = 는 copy(카피는 기본생성자가 안불림) operator or clone  operator 라고 불린다.---> 바로 복사하기 때문에 기본생성자가 안불린다.
2. 
Circle e;
e=c;
//47분
//1,2는 서로 다르다. 1일때 생성자는 불리지 않음, 2일때는 생성자가 불린다.
51m
복사생성자가 생성되어서 만들어진거고 그뒤에 함수가 끝나면 소멸자가 실행된다

블록 assignment 한다---> c1=c2; (객체 할당 또는 객체 치환)

 

  • 4

eference = 참조 
존재하고있는 변수를 참조하여 만드는 변수= reference variabel

int a;
int & b =a;  참조할때 반드시 a가 있어야함// a를 참조한다는 뜻, b는 a와 같다 (메모리 공유) b는a의 별명이다.(대상이 존재해야함) 분신이다. 
// b를 만들때 새로운 메모리가 생기는건 아니다.
한번 레퍼런스된 놈은 배신할수없다.//59분

이걸 어떻게 써야할까? ---어떨때 강력한 도구가 될까?
->1h3m //
void func8(Circle &f)// 함수는 main에 있는 메모리를 가리키게 됨

 

  • 5


*******************정리****************
매우 중요함
1.Circle& rr =c;// 이때 변수를 선언할때 쓰면 레퍼런스 변수를 만든다는 뜻
2. 존재하는 변수앞에 있으면 주소를 뜻함// &c

3.Circle *p;//변수를 선언하면서 *를 쓰면 이때 *는 포인터변수라는 뜻이다.
4.포인터 앞에 있는 *는  그 포인터 주소가 가리키는 값이 됨// *(p).r=4
cf) *(p).r =300; 요놈이랑 p->r=300은 같은 의미이다.

 

사실 reference 변수의 존재의미는 포인터를 대체하기 위함이다.//1h7m**********************************************************
주소를 감추기 위해 레퍼런스 변수를 쓴다.****&&&&&&&&&
레퍼런스는 레퍼런스를 통해서 return 하는 것도 된다.//1h12m
함수속에 로컬변수를 레퍼런스로 넘겨주면 안됨//1시14분// 함수속 변수는 함수가 사라지면서 메모리가 없어지기 때문임

 

  • 6

/1h17m---> 특이한 문법, 처음 봄
 ex)
int gAAA =30;// 전역 변수
int& func10(){
return gAAA;}

int gArr[10];// 전역으로 배열을 만듬

int & func11(int ind){
if(ind<0||ind>=10){
cout<<"error!!!! out of bound of gArr"<<endl;
exit(-1); }
return gArr[ind];}

int main( ){
int& ccc = func10();
ccc=50;
cout<<"gAAA = "<<gAAA<<endl;

for(int i=0;i<10;i++)
func11(i)= i*10;

for(int i=0;i<10;i++){
cout<<"gArr [ "<< i<<"] = "<<gArr[i]<<endl;
1.함수의 인자로 값을 변화시킬떄 사용, 또는 return 값으로 그놈 자체를 지칭할때 사용/// 1h17m 참고
2. 배열의 인덱스를 접근할수있는 대체할수있는 수단로 사용함, 안정적으로 사용할수있는 tool임

C++에서는 c와 다르게 참조리턴이 가능함// 1h25m
참조를 리턴할때 로컬변수를 참조하면 안됨 , 글로벌이나 static을 참조해야함 즉 존재하는 변수를 사용해야함--->배열일때 많이 사용

 

  • 7

복사 생성자
class a;
class b= a;// 이떄 기본 생성자가 불리지 않음// copy or clone 이라고 부름// a가 가진 멤버변수들의 메모리가 비트단위로 복사됨

이떄 class b=a 라는 뜻이다/ 이때는 기본생성자가 안생기고 복사생성자가 생긴다.// 


class b;
 b=a; // 이때는 assignment 임 (할당), copy 가 아니다.

 

  • 8

복사생성자는 reference가 필요하다. 

얕은 복사, 깊은 복사// 5m 48s

동적할당하면 heap에 생성함

우리가 해왔던것은 여태까지 얕은 복사이다.
깊은 복사는 자동으로 안일어남

 

  • 9

포인터의 크기는 4바이트임= 32비트, int도 4바이트/10m

복사생성자
class b = a;  한 클래스에서 오직 1개만 가능********* 그리고 모양이 정해져있다.
인자로 레퍼런스 변수를 가진다. // 12m
 class b =a; === class b(a); 같은 말이다. c++에서 약속한거임

복사생성자가 선언되어 있지 않으면 자동으로 생성이됨


const char*?// 이걸 언제 썻더라? 저번시간 참고해라

문자열을 만들때 항상 마지막에 있는 null 문자를 생각해라


리터럴로 써있는 문자열은 컴파일러가 다른 메모리에 일기 전용으로 만듬//24m50s 
이렇게 리터럴로 주는건 상수인자로 받아야함 위에 const char* 처럼

디버깅 하는법//27m
f10-> 한줄넘어감
f11-> 함수로 들어감
f5 -> 다음 ping 찍은곳으로 넘어감

Student a(10, "kim");
Student b = a; // 29m55s// 이건 얕은 복사이다. 31m  //같은 메모리를 공유하고있음 <------시작

32m 30s 여기에 자세한 설명 있음*****************

 

  • 10

생성자에서 메모리를 동적할당하면 소멸자를 꼭 작성해줘야한다. 34m
메모리 누수 방지//35m
// 38m 자세한 설명*************************

깊은 복사를 하기 위해서는 복사생성자를 만들어야함//39m
Student(const Student& in);
Student::Student(const Student& in)
{
id = in.id;
name = strCopy(in.name);
address = in.address;
}//이게 복사생성자임

const Student &in // 43m
여기서 값을 바꾸는 행위는 봉쇄됨, 컴파일이 걸러냄 --- const 를 붙였기 때문 , 읽기만 가능
in.id++;// 이게 불가능

string은 char*와 다르다.//46m
string은 알아서 깊은 복사를 함// 근데 char*할때는 주의가 필요함

explicit // 분명한,      implicit// 묵시적인

  • 11


student a;
student &b=a;// 이때는 레퍼런스로 받았기 때문에 copy construct가 안일어남