스마트 포인터


스마트 포인터는 동적으로 할당 (힙) 개체에 포인터를 저장하는 개체입니다. 그들은 많은과 같은 내장 C + + 포인터들이 자동으로 객체가 적절한 시간에 지적 삭제할 것을 제외하면 동작합니다. 그들은 동적으로 할당된 객체의 적절한 파괴를 위해 같은 스마트 포인터는 예외의 얼굴에 특히 유용합니다. 그들은 또한 여러 소유자가 공유 동적으로 할당된 객체를 추적하는 데 사용할 수 있습니다.

개념 스마트 포인터는 객체가 지적 소유로 볼 수 있으며, 그것이 더 이상 필요하지 않은 개체의 삭제에 대한 책임을 따라서.

스마트 포인터 라이브러리 여섯 스마트 포인터 클래스 템플릿을 제공합니다 :


scoped_ptr<boost/scoped_ptr.hpp>단일 개체의 단순 단독 소유. Noncopyable.
scoped_array<boost/scoped_array.hpp>배열의 간단한 단독 소유. Noncopyable.
shared_ptr<boost/shared_ptr.hpp>개체 소유권은 여러 포인터 사이에 공유.
shared_array<boost/shared_array.hpp>배열 소유권은 여러 포인터 사이에 공유.
weak_ptr<boost/weak_ptr.hpp>비 소유 shared_ptr가 소유한 개체의 관측합니다.
intrusive_ptr<boost/intrusive_ptr.hpp>임베디드 참조 카운트와 개체의 소유권을 공유.


 auto_ptr 템플릿 :이 템플릿은 표준을 보완하기 위해 고안되었습니다.

using namespace std;
class Stu
{
//*******************************************************originStu*************************************
class OriginStu
{
int num;
string name;
int rcnt;
public :
OriginStu(int _num,string _name)
{
num = _num;
name = _name;
rcnt = 1;
}
void AddRef()
{
rcnt++;
}
int Release()
{
rcnt--;
return rcnt;
}
};
//*******************************************************originStu*************************************
OriginStu *ostu;
public :
Stu(int _num,string _name)
{
ostu = new OriginStu(_num,_name);
}
Stu(const Stu &stu)
{
*this = stu;
ostu->AddRef();
}
~Stu()
{
if(ostu->Release()){
return;
}
delete ostu;
}
};


void main()
{
Stu s(2,"홍길동");
Stu s2(s);
}





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


#include "stdafx.h"
using namespace std;

template<typename T>
class CountedPtr
{
private:
  
  struct Impl
  {
    T* p;
    size_t refs;

    Impl(T* pp) : p(pp), refs(1)  {}
    ~Impl()              { delete p; }
  };

  Impl* impl_;

public:
  explicit CountedPtr(T* p) : impl_( new Impl(p))    {}
  ~CountedPtr()                    { Decrement(); }
  CountedPtr(const CountedPtr& other) : impl_(other.impl_)    { Increment(); }
  CountedPtr& operator=(const CountedPtr& other)
  {
    if(impl_ != other.impl_)
    {
      Decrement();
      impl_ = oter.impl_;
      Increment();
    }
    return *this;
  }
  T* operator->() const
  {
    return impl_->p;
  }
  T& operator*() const
  {
    return *(impl_->p);
  }
private:
  void Decrement()
  {
    if( --(impl_->refs) ==0)
    {
      delete impl_;
    }
  }

  void Increment()
  {
    ++(impl_->refs);
  }
};

int main()
{
  int *a = new int[2];
  
  CountedPtr<int> intPtr(a);


  return 0;
}

[출처] 스마트





#include


 <iostream>

using namespace std;


class Parent

{

        int x;

public:

        virtual void foo() { cout <<" Parent::foo" << endl;}

};

 

class Child : public Parent

{

        int y;

public:

        virtual void foo() { cout << "child::foo"<< endl; }  

        // 가상함수는inline 될수없다. inline : 컴파일시수행.  가상함수: 실행시간수행

};

 

int main()

{

        Parent p;

        cout << sizeof(p) << endl;   // p 는4바이트가아니고8바이트(가상함수테이블포인터추가)

 

        Child c;

        cout<< sizeof(c) << endl;   // x,y까지8바이트+ 가상함수테이블포인터4바이트= 12바이트

 

        Parent* pc = &c;

        pc->foo();    

      // (*pc)[0]()의기계어코드를만들어낸다.이게 포인트다. 이름을 보지 않고 배열의 인덱스로 함수를 

      // 찾아간다. 이걸 기억해두고 아래 문제를 생각한다. 결국 이 코드는

      // 가상함수테이블의첫번째공간으로..어디로 갈지 실행시간에(vptr을 보고) 결정된다

}

 

 

 

 

 

class A

{

        int x;

public:

        virtual void foo() { cout << "A::foo" << endl; }

};

 

class B       // A와상속관계가아님

{

        int y;

public:

        virtual void goo() { cout << "B::goo" << endl; }

};

 

int main()

{

        A a;

        B* p = (B*)&a;

 

        p->goo();   // 둘다가상함수가아니라면B:goo() 가실행된다.

}

 

// foo와goo 가둘다가상함수라면foo()가호출.

// (코드에서타입은B* 이지만&a가대입되어a의주소를가진다.따라서가상함수테이블도A의그것으로가진다.

 

// 런타임시간에p->goo 는B의goo 가있는줄알고가상함수테이블을따라가서(첫번째로간다) 그곳을참조하는데가보니까

//  A::foo 가있어서호출해버린다-_-.. 배열인덱스처럼따라간다.)

// foo 가 가상이고 goo가 가상이 아니라면 goo()가호출. A는 vptr이 있지만 B는 vptr이 없다. 그래서 A를 대입해도 B는 테이블을 안만든다. 그래서 그냥 goo로..

// goo 가 가상이 아니고 goo가 가상이라면 에러.(쓰레기값을참조한다) A 함수에는 vptr이 없다고!

 

 

class A

{

public:

        virtual void foo() { cout << "A::foo" << endl; }

};

 

class B : public A

{

public :

        virtual void foo() { cout << " B:: foo " << endl; }

};

 

void hoo(A* p, A& r, A o)

{

        p->foo();     // B::foo

        r.foo();      // B::foo

        o.foo();  // 값으로전달받는다. A::foo

}

 

int main()

{

        B b;

        hoo(&b,b,b);

}




클래스에 가상 함수가 포함되면 클래스 멤버에 vptr이라는 포인터가 추가된다. 코드에는 나타나지 않고 디버그중에 조사식으로 확

인할 수 있다. vptr은 해당 클래스의 가상함수 테이블의 주소를 가지고 있다. 해당 클래스의 virtual 선언에 따라 클래스가 실행해야

할 가상함수의 함수포인터가 배열을 이루고 있음을 확인할 수 있다. 이것을 가상 함수 테이블이라 한다.

#클래스 템플릿(class template)

템플릿은 컴파일시 내부적으로 템플릿 인자로 넘어온 자료형을 적용하여 새로운 클래스를 하나 생성하게 된다. 그리고 컴파일러는 생성한 클래스를 가지고 작업을 수행하게 된다. 템플릿 클래스는 선언시 자료형에 상관없는 범용클래스로 만든후 객체 생성시 자료형을 지정해주면, 지정한 자료형에 맞는 클래스 인스턴스가 생성된다.

template <typename 식별자> 클래스 {  //클래스 정의

  //내용

};

template <typename 식별자>

void 클래스명<식별자>::멤버함수() {  // 맴버 함수 구현

  //내용

}


//***************************************************************************
// 템플릿 클래스 !!
//***************************************************************************


#include <iostream>
using namespace std;
// 배열 추상화 !!
// 1) 속성!!
// --> Data buffer !!
// --> 배열의 길이
// 2) 행동 !!
// --> 입력
// --> 삭제
// --> 출력
template <typename T>
class Array
{
private :
T *m_Buf;
int m_size;
public :
Array()
{
cout << "최대 배열의 크기 입력 ";
cin >> m_size;
m_Buf = new int[sizeof(T)]();
//memset(m_Buf,0,40);//******************//
 menu();
}
~Array(){}
int & operator[](int idx)
{
return m_Buf[idx];
}
void push_back()
{
if(m_Buf[m_size-1] !=0){
m_Buf = (int *)realloc(m_Buf,_msize(m_Buf)+4);
m_size = _msize(m_Buf)/sizeof(int);
cout << "맨뒤에 넣을 값을 입력 ";
cin >> m_Buf[m_size-1];
}
else{
cout << "맨뒤에 넣을 값을 입력 ";
cin >> m_Buf[m_size-1];
}
}
void pop_back()
{
m_Buf[m_size-1] = 0;
cout << "["<< m_size << "]" << "맨뒤에 배열의 값을 뿅~~~~~" << endl;
m_Buf = (int *)realloc(m_Buf,_msize(m_Buf)-4);
m_size = _msize(m_Buf)/sizeof(int);
}
void push_front()
{
if(m_Buf[0] !=0){
m_Buf = (int *)realloc(m_Buf,_msize(m_Buf)+4);
m_size = _msize(m_Buf)/sizeof(int);
m_Buf[m_size-1] = 0;
for(int i=m_size;i>0;i--){
m_Buf[i-1] = m_Buf[i-2];
}
cout << "맨앞에 넣을 값을 입력 ";
cin >> m_Buf[0];
}
else{
cout << "맨앞에 넣을 값을 입력 ";
cin >> m_Buf[0];
}
}

void pop_front()
{
//cout << "맨앞에 배열의 값을 뿅~~~~~" << endl;
for(int i=0;i<m_size;i++){
  m_Buf[i] = m_Buf[i+1]; 
}
m_Buf = (int *)realloc(m_Buf,_msize(m_Buf)-4);
m_size = _msize(m_Buf)/sizeof(int);
cout << "["<< 0 << "]" << "맨앞에 배열의 값을 뿅~~~~~" << endl;
}
void Add()
{
int num=0;
cout << "몇번째 ?? " <<endl;
cin >> num;
if(m_Buf[num-1] !=0){
m_Buf = (int *)realloc(m_Buf,_msize(m_Buf)+4);
m_size = _msize(m_Buf)/sizeof(int);
m_Buf[m_size-1] = 0;
for(int i=m_size;i>num-2;i--){
  m_Buf[i-1] = m_Buf[i-2]; 
}
cout<< "숫자 입력 ";
cin >> m_Buf[num-1];
}
else{
cout<< "숫자 입력 ";
cin >> m_Buf[num -1];
}
}
void Pop_Select()
{
}

void Show()
{
for(int i=0;i<m_size;i++){
cout <<" "<< "["<< m_Buf[i] <<"]" ;
}
cout << endl;
}
void ascending_selection_sort ()    // 오름차순
{
cout << " 오름 차순 "<< endl;
int i, j, min;
for ( i = 0; i < m_size-1; i++ )
{
for ( min = i+1, j = i+2; j < m_size; j++ )
if ( m_Buf[min] > m_Buf[j] ) min = j;
  if ( m_Buf[min] < m_Buf[i] ){
  int t = m_Buf[i]; m_Buf[i] = m_Buf[min]; m_Buf[min] = t; 
 }
}
  Show();
void descending_selection_sort ()    // 내림차순
{
cout << " 내림 차순 " << endl;
int i, j, max;
for ( i = 0; i <m_size-1; i++ )
{
for ( max = i+1, j = i+2; j < m_size; j++ )
if ( m_Buf[max] < m_Buf[j] ) max = j;
if ( m_Buf[max] > m_Buf[i] ) {
int t = m_Buf[i]; m_Buf[i] = m_Buf[max]; m_Buf[max] = t; 
}
}
Show();
}



int Modi()
{
int num=0;
system("cls");
cout << "[1] 배열추가" << endl;
cout << "[2] push_back" << endl;
cout << "[3] pop_back" << endl;
cout << "[4] push_front" << endl;
cout << "[5] pop_front" << endl;
cout << "[6] 배열사이꺼 뺴기 " << endl;
cout << "[7] show " << endl;
cout << "[8] 내림차순정렬" << endl;
cout << "[9] 오름차순정렬" << endl;
cout << "[0] 종 료" << endl;
cin >> num;

return num;
}
void menu()
{
int num=0;
while((num = Modi()) != 0)
{
switch(num)
case 1: Add(); break;
case 2:push_back(); break;
case 3:pop_back(); break;
case 4:push_front();break;
case 5:pop_front(); break;
case 6:Pop_Select(); break;
case 7:Show(); break;
case 8 :descending_selection_sort(); break;
case 9:ascending_selection_sort () ;break;
default : cout << "error" << endl;
}
system("PAUSE");
}
}
Array &operator ()(Array &ar)
{
//ar.Show();
return ar;
}
};

template <typename T>
ostream & operator <<(ostream & os, Array<T> &ar)
{
ar.Show();
return os;
}

 

// 단점
// 1) 정적인 배열의 크기 ==> 동적배열 !!
// 2) 인덱스를 통한 접근이 안됨 ==> 연산자 오버로딩 !!
// 3) 시작위치의 주소값을 같지 않는다 ==> 객체 출력자 구현 !!

void main()
{
Array<int> ar;
cout << ar << endl;
//ar.Show();
//ar.push_back();
}


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

스마트 포인터  (0) 2016.11.30
가상함수테이블  (0) 2016.11.30
템플릿(Template) - 함수 템플릿, 클래스 템플릿, 템플릿의 특수화  (0) 2016.11.30
클래스  (0) 2016.11.30
구조체  (0) 2016.11.30

+ Recent posts