2012. 8. 14. 10:38

#include<iostream>


using namespace std;



///////////////////////////////////////////////////////////////////////////////////////////

// 객체의 얕은 복사 이야기

// 1. 생성자에서 자원을 획득할 경우, 소멸자에서 자원을 반납하자! RAII

// RAII : resource acquision is initialize ( 자원을 획득하는 것은 객체의 초기화 이다.)

// 2. 클래스 내부에 포인터 멤버가 있다면 컴파일러가 제공하는 복사 생성자는 얕은 복사 현상을 일으킨다.

// 사용자는 반드시 이문제를 해결해야 한다.

//

// 3. 해결책

// (A) 깊은 복사 

// (B) 참조 계수

// (C) 소유권 이전 

// (D) 복사 금지

//

///////////////////////////////////////////////////////////////////////////////////////////

/*

class Cat{


char *name;

int age;


public : 

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}


*/


///////////////// (A) 깊은 복사 /////////////////////////////////////

/*

class Cat{


char *name;

int age;


public : 

//깊은 복사를 구현한 복사 생성자 


Cat(const Cat & c ): age(c.age) // 1. 포인터가 아닌 멤버는 그냥 복사

{

name = new char[strlen(c.name+1)];

strcpy(name, c.name); // 메모리를 복사

}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}*/


/*

/////////////////////////////////////////////////////////////////////////////////////


////////////////// (B)참조계수법: 메모리를 복사하지말고 카운트를 하자! //////////////////

class Cat{


char *name;

int age;

int *pRef;

public : 

// 참조 계수를 기반으로 만들어진 복사 생성자

Cat(const Cat&c) : name (c.name), age(c.age),pRef(c.pRef){

++(*pRef);

}

Cat (const char *n, int a): age(a){

pRef = new int(1); //1개를 1로 초기화 

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){

if(--(*pRef)==0){


delete[] name;

delete pRef;

}

}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.


//c1.name = "AAA"; //이순간 C1 C2는 자원(이름)을 분리해야한다.

//copy on write (COW)라는 기술~

}


*/

///////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////// (C) 소유권이전의 복사생성자 기술1 ////////////////////////////

/*

class Cat{


char *name;

int age;


public :


//swap 같등을 만들때 아주 좋은 방식이다! 차세데 C++ ㅇ는 move 생성자라고 부른다

// 현재는 C++ 표준인 auto_ptr<> 이 이기술을 사용한다


//소유권 이전의 복사 생성자 기술!! 

Cat(Cat & c):name(c.name),age(c.age) //얕은 복사

{

c.name=0;

c.age=0;


}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}


*/

/*

//////////////////////////////////(D) 복사금지 기법///////////////////////////////////////

class Cat{


char *name;

int age;

//private 복사 생성자 .. 복사 금지 할떄 사용하는 기술

Cat (const Cat & c); //선언만한다 1.일단선언이 있으므로 컴파일러는 디폴트복사를 제공하지 않는다.

//2.어딘가에서 호출하는 코드가 있으면 구현이 없으므로 링크 에러이다.

//  멤버함수에서도 호출 할 수 없다.



//보통 복사를 금지하면 대입도 금지한다

void operator=(const Cat&);

public :

void foo(){

// Cat c1("A",10);

// Cat c2(c1); //OK 에러를 내게한다.


}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

// Cat c2(c1); //캄파일 시간에러가 나오게 하자! 



}



//////////////////////////////////////////////////////////////////////////////////////////////


*/



////////////////////////////////////////////////////////////////////////////////

// 복사 연산자는 너무나 유용하기 때문에 따로 클래스를 만들어 사용하는경우가 많다,

//

//////////////////////////////////////////////////////////////////////////

class uncopyable

{

private:

uncopyable(const uncopyable &);

void operator=(const uncopyable &);

};

//이것을 상속 받아 사용하면된다. 


class Cat : private uncopyable{


char *name;

int age;


public :

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

// Cat c2(c1); //캄파일 시간에러가 나오게 하자! 



}

///////////////////////////////////////////////////////////////////////////


Posted by k1rha