본문 바로가기
코스웨어/10년 시스템제어

시스템제어 5월 25일 일일보고서 10번 문현철

by 알 수 없는 사용자 2010. 5. 25.
728x90
반응형

auto_ptr
auto_ptr 동적으로 할당된 메모리도 자동으로 해체하는 기능을 가지는 포인터의 래퍼클래스
new 선언후 delete 빼먹는 실수를 방지
#include <memory>
template<typename T>class auto_ptr
예)
auto_ptr <double>rate(new double);
*rate=3.1416;

namespace

명칭들이 기억되는 영역이며 명칭의 소속공간  일명: 이름을 담는 통

기본형식
namespace 이름
{
      여기에 변수,함수 선언

}

using namespace std;

C++ 표준 라이브러리는 모두 std 네임스페이스에 선언되어 있다

네임 스페이스 작성규칙
*네임스페이스의 이름은 가급적이면 길게 쓰고 또한 중복되지 않는 고유한 이름으로 작성
*네임스페이스는 반드시 전역영역에서 선언해야 한다.
*네임스페이스끼리는 중첩가능하다.
*네임스페이스는 항상 개방되어 있다.(같은 네임스페이스를 여러번 나누어 명칭선언 할수 있다)
*네임스페이스가 이름을 가지지 않을 수 있다.

namespace{

             int internal;            //전역변수와 동일

}                           
*다중 모듈프로젝트에서 함수 본체의 위치를 주의해야 한다.

복사생성자

객체 두개가 같은 메모리를 공유하고 있으면 한쪽에 값을 변경하면 다른쪽도 영향을 받게되어
서로 독립적이지 못하게 된다. 이 객체들이 파괴(소멸)될때 문제가 발생하여 각 객체의 소멸자가
번지를 따로 해제하기 때문이다. 같은 값을 다른 객체의 소멸자에서 두번실행하기 때문에 이미
해체된 메모리를 다시 해제하려고 시도하므로 실행중 에러가 된다.
복사생성자는 자신과 같은 타입의 다른 객체에 대한 레퍼런스를 전달받아서 이 레퍼런스로 부터
자신을 초기화 한다.
복사 생성자가 호출되는 시점은 세가지로 분류할수 있다
기존의 생성된 객체로 새로운 객체를 초기화 하는경우
함수 호출시 객체를 값에 의해 전달하는 경우
함수 내에서 객체를 값에 의해 리턴하는 경우

this의 의미

멤버 함수의 본체에서 this 키워드는 지금 이 함수를 실행하고 있는 객체 그 자체를 표현하는 1인칭 대명사이다.
멤버 함수가 객체를 칭할 필요가 있을때 this를 직접 사용한다.
객체가 자신을 스스로 삭제하고자 할 때도 this 키워드를 쓴다.delete this;
호출한 객체를 멤버 함수로 전달하는 방법은 컴파일러마다 조금씩 다르다.
CX레지스터(목적을 위한 레지스터이며 CX는 루프및 반복에 쓰인다.)를 사용하는 경우도 있고 첫번째 인수로 전달하는 컴파일러도 있다.
중요한 것은 멤버 함수를 호출 할때 호출한 객체의 정보가 함수에게 암시적으로 전달된다. 함수에서 자신을 호출한 객체의 번지를 인수로
전달받으며 이때 전달받은 숨겨진 인수를 this라고 하는데 호출한 객체의 번지를 가리키는 포인터상수이다.
함수의 호출규약에서 this는 thiscall를 사용한다.
자기 자신에 대한 레퍼런스를 리턴할때는 *this표현식을 사용한다.

목적을 위한 레지스터

종류    구성           용도
AX    AH, AL    수학 연산, I/O 연산, INT 21
BX    BH, BL   Base 또는 Pointer
CX    CH, CL   루프 및 반복
DX    DH, DL   다양한 데이터, 문자 출력

H는 high를 의미한다 L는 low를 의미한다
32비트는 4개의 레지스터가 추가되어 EAX,EBX,ECX,EDX이다.E는 32비트로 'Extended'를 의미

AX에 어떤 값을 부여하면 AH가 그 값의 첫 부분을 포함하고, AL은 마지막 부분을 포함한다
AX에 DEAD를 부여하면 AH는 DE를 포함하고 AL은 AD를 포함한다.
|             EAX              |
+-----+-----+-----+----+
|       |        | AH   | AL  |
+-----+-----+-----+----+
                  |     AX      |

thiscall

클래스 멤버함수에 대해서만 적용되며 ecx로 객체의 포인터(this)가 전달된다는 것이 특징이며 나머지 규칙은 __stdcall과 동일하다.
이 호출규약은 컴파일러가  멤버함수에 대해서만 특별히 적용하는것이므로 일반함수에는 이호출 규약을 적용할수 없다.
thiscall은 이 호출 규약의 이름일 뿐 키워드가 아니기 때문에 함수원형에 thiscall이라고 사용불가하다.
멤버 함수이기만 하면 컴파일러가 알아서 thiscall 호출규약을 적용한다.


#include <iostream>

using namespace std;

class sca
{
public:
  sca &operator =(const sca& T) 
  {
    cout<<"종속 대입 연산자 호출\n";
    return *this;
  }
};
class Test:public sca  //class sca를 상속하는 Test 클래스
{
public:
  int *p;
  Test &operator =(const Test & T) //Test뒤에 &를 붙였는데 참조에 의한 리턴을 하고있다
  {    //대입연산자는 자신과 같은 타입의 다른 객체를 대입받을때 사용하는 연산자 이므로
       //객체 자체와 직접적인 연관이 있기 때문에 클래스의 멤버 함수로만 정의 할수 있고
       //전역함수로 정의 할수 없다.
    if(this==&T)//자기 대입방지
    {
      return *this//자기 자신에 대한 레퍼런스를 리턴한다.
    }
    sca::operator =(T);  //함수처럼 인자를 넣어서 호출한다.sca 클래스의 대입연산자를 호출한다
    cout<<"대입 연산자 호출\n";
    *(this->p)=*(T.p); //int *p이기 때문에 *로 타입을 맞추어 주어야한다.
    return *this
  }
  Test(int k)   //암시적인 생성자선언
  {
    p=new int//메모리 동적할당
    *p=k;      //동적할당후 값을 대입한다.
  }
  Test(const Test & T) //객체를 인자로 받는 복사생성자
  {
    sca::operator =(T); //sca 클래스의 대입연산자를 호출한다
    p=new int;
    *p=*(T.p); 
  }
  ~Test()//생성자내에서 메모리를 동적할당 했으므로 소멸자 정의후 해체함
  {
    cout<<"소멸자\n";
    delete p;  
    cout<<"재확인\n";
  }
};

int main()
{
  Test Obj1(5);       
  Test Obj2(Obj1);  //복사 생성자호출 
  Test Obj3(3);
  //Test Obj2(2);
  Obj3=Obj2=Obj1; //대입연산자 오버로딩   Obj1의 값이 5이므로 객체 각각 5가 대입된다.
  Obj1=Obj1; //포인터를 복잡하게 사용하다 보면 이런경우가 생긴다.
  cout<<*(Obj1.p)<<endl;   //5출력됨
  cout<<*(Obj2.p)<<endl;   //5출력됨
  cout<<*(Obj3.p)<<endl;   //5출력됨
  //객체가 소멸될때 컴파일러가 자동으로 호출된다. 객체가 3개 선언되어서 3번호출된다.
    return 0;




실행결과



템플릿(Template)
쉽게 생각해서 붕어빵틀이라고 생각하면 된다.
함수 템플릿은 함수를 만들기 위한 형틀에 지나지 않고 그 자체가 함수는 아니다. 컴파일러는 함수 템플릿 정의문으로 부터 함수의
모양(붕어빵틀)만 기억했다가 실제 함수가 호출되면 타입에 맞는 함수를 작성한다. 함수 템플릿으로 함수를 만드는 것을
인스턴스화(Instantiation)이라 한다.함수 템플릿으로 만든 함수를 템플릿 함수라고 하는데 용어가 비슷하여 헷갈릴수가 있다.
함수 템플릿은 함수를 만들기 위한 템플릿이고 템플릿 함수는 템플릿으로 부터 만드는 함수이다.

size_t   
Unsigned integral type이다 문자열이나 메모리의 사이즈를 나타낼때 사용된다.
typedef unsigned int size_t; 이렇게 정의 되어 있음.
sizeof(size_t)를 해보면 32비트 환경에서는 4바이트 64비트 환경에서는 8바이트 각각 출력된다.

#include <iostream>

using namespace std;                      
//기본적으로 메모리 정리는 4바이트이다
#pragma pack(1) //메모리 정리를 1바이트 단위로 한다
class Test
{
public:
  Test()
  {
    cout<<"test생성자 구동\n";
  }
  int k;     //4바이트
  int j;     //4바이트
  float f;   //4바이트
  char a;    //1바이트
};
#pragma pack(4//1바이트에서 4바이트로 재정의
template<class Z> //함수 템플릿 선언
class Array
{
public:
  Array()
  {
    Elems=new Z[10];
    cout<<"크기:"<<sizeof(Z)<<endl;
    NumElems=10;
  }
  ~Array()
  {
    delete []Elems;
  }
  void SetSize(size_t value)
  {
    cout<<"SetSize()호출\n";
  }
  size_t GetSize()
  {
    cout<<"GetSize()호출\n";
  }
  void SetElem(size_t index,Z value)
  {
    cout<<"SetElem()호출\n";
  }
  Z GetElem(size_t index)
  {
    cout<<"GetElem()호출\n";
    return Elems[0];
  }
private:
  Z *Elems;
  size_t NumElems;
};
int main()
{
  Array<int> Obj1;  //크기 4출력 Z로 선언된 부분이 int로 바뀐다.
  Array<short> Obj2;  //크기 2
  Array<char> Obj3;   //크기 1
  Array<Test>Obj4; //크기 13 객체10개를 할당받아 생성자를 10번호출. 
  cout<<sizeof(Obj1.GetElem(1))<<endl;   //4
  cout<<sizeof(Obj2.GetElem(1))<<endl;   //2
  cout<<sizeof(Obj3.GetElem(1))<<endl;   //1
  cout<<sizeof(Obj4.GetElem(1))<<endl;   //13
  return 0;
}
실행결과



STL
(Standard Template Library)
C++에서 템플릿 수준의 라이브러리를 제공한다.
STL의 특징
(장점)
1.일반화를 지원한다.
2.컴파일 타임 메커니즘사용으로 실행시 효율이 좋다
3.객체지향적이지 않다.
4.표준이어서 이식성이 확보된다.
5.소스가 공개되어 있어서 확장이 가능하다
(단점)
1.템플릿기반으로 인해 코드가 비대해지는 문제가 있다
2.STL로 작성한 코드는 가독성이 떨어져서 알아보기 힘들다.
3.배우기가 쉽지 않아 배워서 금방 활용할수 있는 라이브러리가 아니다.
728x90