Search Results for 'C++'

22 POSTS

  1. 2013.01.03 erase, clear 주의점
  2. 2012.12.28 메모리 누구 탐지
  3. 2012.12.27 interface를 사용한 종속성 최소화
  4. 2012.10.16 #pragma pack
  5. 2012.09.04 깊은복사 얕은 복사
  6. 2012.09.04 스마트 포인터
  7. 2012.08.13 오버로딩, 오버라이딩
  8. 2012.08.13 iterateor
  9. 2012.08.13 vector-소스 한개
  10. 2012.08.13 vector

erase, clear 주의점

Posted 2013. 1. 3. 16:18

삭제시

for( ; iter != data.end() ; )

{

iter = data.erase(iter);

}

iter의 erase는 해당데이터를 삭제하고 다음 데이터를 반환한다.

만약 총 10개의 데이터가 들어 있다 치고 10개를 삭제할시

for( ; iter != data.end() ; ++iter )    

{

iter = data.erase(iter);

}

붉은색처럼 해버리면 1, 2, 3, 4, 5 순으로 삭제되는게 아니라, 1, 3, 5, 7, 9 로 삭제 되 버린다.

흔히 하기 쉬운 실수임.

 

또.. 동적할당도 직접 해제해 줘야하니

delete 부터 해주고 erase 하자

메모리 누구 탐지

Posted 2012. 12. 28. 12:25

#include <crtdbg.h>        // head 추가

 

void main()

{

char* p = new char[20];        // 메모리 할당

_CrtDumpMemoryLeaks();      // 메모리릭 탐지

}

 

브레이크 포인터를 _Crt에 걸고 보면 출력에

 

'MemLeakDebug.exe' : exe ' : Loaded 'C:\win................

'MemLeakDebug.exe' : exe ' : Loaded 'C:\win................

Detexted memory leaks!

Dumping objects ->

{50} normal block at 0x00392892, 20bytes long

.......

.............

어쩌고 뜬다.

 

요게 메모리 누수 발견이라고 알려주는 거다.

여기서 볼건 {50} 이다. {50}이라는 메모리 참조값을 가지는 지점이 해제되지 않았다는 것이다.

{50}을 찾으면 된다.

 

void main()

{

_CrtSetBreakAlloc(50);            // 메모리 할당받는 곳 윗줄에 추가 해주자.

char* p = new char[20];

_CrtDumpMemoryLeaks();

}

그러면 {50} 메모리 지점을 생성하려고 할 때 에러창이 뜨면서 빠염..

 

 

주의 할 점은

정상적으로 메모리해제를 하게 되더라도 위치가 _CrtDumpMemoryLeaks(); 밑에서 하게 되면

메모리 누수로 감지 하게 된다.

ex) char* p = new char[20];

_CrtDumpMemoryLeaks();

delete [] p;

일때 누수로 감지하게 됨.

 

_CrtDumpMemoryLeaks(); 위에서 하던지 아니면 함수 밖에서 따로 하던지 위치를 잘 봐야 한다.

interface를 사용한 종속성 최소화

Posted 2012. 12. 27. 14:29

자신의 기능을 노출 시키자

1. 하나의 인터페이스는 서비스를 제공하는 하나 이상의 메소드를 정의

2. COM 개체는 반드시 하나의 IUnknown 인터페이스를 제공

3. COM 개체의 고유한 기능을 노출하는 하나 이상의 인터페이스 제공

4. 순수가상함수만을 멤버로 포함하는 추상클래스의 모임

5. 인터페이스를 상속받은 인터페이스의 가상함수는 반드시 전부 재정의 해야 한다.

 

#include <iostream>

 

class ICall

{

public:

virtual ~ICall(){};

virtual void call () = 0;

};

 

class callme : pulic ICall

{

public:

~callme(){};

void call(){ std::cout << " call me " << std::endl; };

};

 

class user

{

public:

void what( ICall* ic ){ ic->call(); };

};

 

void main()

{

callme* c = new callme;

user u;

u.whet(c);

}

이렇게 되면 .h파일을 include해 줘야 하며 컴파일도 새로 해야 하며 종속적이게 된다.

 

마소의 COM/DCOM 에서는 아래와 같이 구현 함으로 include 및 컴파일 속도 종속성을 해결해 줄수있다

 

interface ICall                        // call에 대한 interface 생성

{

virtual ~ICall(){};

virtual void call() = 0;

};

 

class callme : public ICall

{

public:

~callme(){};

void call(){ std::cout << "call me" << std::endl; };

};

 

class user

{

public:

void what( ICall* ic ) { ic->call(); };

};

 

void main()

{

callme* c = new callme;

user u;

u.what(c);

}

 

//---------------------------------------

인터페이스와 추상클래스의 차이점

추상 클래스( abstract class )

1.추상 클래스가 되려면 추상 메소드가 1개 이상인 클래스(단, 추상 field는 없다)

-> ( void make() )

2. 추상 클래스를 상속했지만 추상 메소드를 오버라이딩 하지 않거나 인터페이스를 구현했지만

메소드를 구현하지 않았을때

3. 특정 메소드를 강제로 상속하여 사용하려는 경우

4. 특징

1. 자기자신의 이름으로 자기자신을 생성 할 수 없다.

2. 추상 클래스를 상속한 자식 클래스의 객체를 생성하여 사용한다.

3. 선언과 구현을 분리 시킨다.

4. 부모는 자식보다 추상적 또는 일반적이다.

5. 부모의 메소드를 자식의 특징에 맞게 오버라이딩 한다.

 

인터페이스( interface )

1. 인터페이스가 되려면 abstract method로만 이루어진 클래스

2. void show();와 같이 바디( {} ) 를 붙이지 않는다.

   메소드 이름을 나열한다.

3. private은 사용하지 말고 기본 접근 제한자 이상을 사용하자.

   void show(); 는 public abstract void show(); 가 된다. 그래서 추상 메소드라 불린다.

4. 변수는 자동으로 상수가 된다.

-> int a = 1; ==> public final static int a = 1;

5. 인터페이스의 추상 메소드를 구현하지 못하면 자식 클래스는 추상클래스가 된다.

6. 인터페이스가 여러개일때 ","을 사용 한다.

-> A implements IC, ID

7. 상속이 우선이다

-> A extends B implements IC, ID

8. 인터페이스는 여러개의 인터페이스를 상속 할 수 있다.

-> ex IA extends IC, ID

9. 자기 자신의 이름으로 자기자신을 생성 할 수 없다.

10. 커플링을 떨어뜨린다.

11. 선언과 구현을 분리 시킨다.

12. 다중상속을 흉내낸다.

 

 

 

 

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

깊은복사 얕은 복사  (0) 2012.09.04
스마트 포인터  (0) 2012.09.04

#pragma pack

Posted 2012. 10. 16. 14:14

기본적인 윈도우 환경에서 데이터정렬은 4바이트를 기준으로 이루어 진다.

cpu가 32바이트인 컴퓨터에서 4바이트씩 처리하는게 가장 빠르기 때문이다.

#pragma pack 은 이 구조체정렬을 몇 바이트씩 pack을 할지 정할수 있는것이다.


예를 들어.

struct AAA

{

int a;

short b;

};

AAA라는 구조체가 있다.

멤버변수로 int형 a와 short형 b가 있다. 두 변수를 합하면 6바이트가 된다.

하지만 sizeof(AAA)를 하면 8바이트가 나오게 된다.

왜냐면 구조체 정렬이 4바이트로 되어 있기 때문이다.

short는 2바이트면 되지만 메모리 구조상 4바이트를 먼저 할당할 다음 2바이트를 사용하게 된다.

그러면 남은 2바이트는 사용하지않는 공간이 되어 버린다.


AAA bbb;

sizeof(bbb.a)  sizeof(bbb.b) 하면 제대로 4바이트 2바이트가나오지만 묶으면 그렇지 않다


그렇게 데이터 교환중에 의도치 않은 현상이 발생 할 수도 있다.

묶었을때도 1바이트씩 처리되게 바꿔 주면 됨.

#pragma pack(1)        // 묶어주고

struct AAA

{

int a;

short b;

};

#pragma pack()        // 원상태로


사용 후 복구 시켜 줘야 한다.

앞서 말했다 싶이 4바이트씩 처리하는게 가장 빠르다고 했다.

복구 시키지않으면 시스템이 저하될수도 있다.



깊은복사 얕은 복사

Posted 2012. 9. 4. 15:09

얉은 복사 : 참조한 메모리 주소 복사

깊은 복사 : 복사할 주소한의 데이터 값을 복사

 

차이점

객체를 복사하는 과정에서 복사생성자가 없을 경우 생성자에서 동적할당된 메모리르 두 객체가 동시에 참조하게 된다 이떄 발생하는 문제로는 여러가지가 있겠지만 두개의 객체가 한 메모리주소를 공유하게 되고 클래스의 경우 프로세스종료시에 소멸자를 호출하게 되는데 소멸할때 호출될 메모리는 하나지만 객체를 두번이나 delete를 하게 된다. 첫 객체가 소멸될땐 문제가 없겠지만 그 다 음 복사된 객체는 소멸할때 이미 없어진 객체를 또 없애는 액션을 취하며 문제가 발생한다.

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

interface를 사용한 종속성 최소화  (0) 2012.12.27
스마트 포인터  (0) 2012.09.04

스마트 포인터

Posted 2012. 9. 4. 15:04

포인터는 아니지만 포인터의 역할을 하는것

 

사용 이유

생성과 소멸 작업을 조절 할 수 있다

스마트 포인터가 생성되고 소멸되는 시기를 결절 할 수 있다. 대부분의 스마트 포인터는 생성 될 때 기본값 0을 가지기 때문에 값을 주지 않으면 초기화되지 않은 포인터가 일으키는 골치아픔을 원칙적으로 봉쇄한다. 어떤 스마트포인터는 객체를 가리키고 있던 최후의 포인터가 소멸될때 자동으로 그 객체를 삭제한느 기능도 가지고 있다.

 

복사와 대입 동작을 조절 할 수 있다.

스마트포인터가 복사되거나 대입될 떄 일어나는 일을 직접 결정 할 수 있다. 어떤 경우는 포인터가 가리키는 객체까지 자동으로 복사하던지 대입하도록, 즉 깊은 복사를 수행하도록 할 수 있겠고, 어떤 경우는 포인터 자체만 복사하던지 대입할수 있도록 할 수 있다. 이 외의 경우에는 이런 동작을 전혀 허용하지 않을수도 있다. 무엇은 원하든 상관없이 바라는 바를 그대로 이행하는 포인터가 스마트포인터다

 

역참조 동작을 조절 할 수 있다.

사용자가 스마트포인터가 가리키는 객체를 가져오려고 할 떄 특정 상황이 일어나게 하는것도 사용자가 결정 할 수 있다.

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

interface를 사용한 종속성 최소화  (0) 2012.12.27
깊은복사 얕은 복사  (0) 2012.09.04

오버로딩, 오버라이딩

Posted 2012. 8. 13. 22:22

오버로딩

 함수가 중복될때.. 이미 있는 함수를 또 만드려고 할떄 오버로딩

 

오버라이딩

 상속관계에 놓였을때 이미 만들어둔 함수를 자식 클래스에서 재정의 하려고해 했을때 생김.

재정의 하고 싶으면 부모클래스에서 virtual을 선언해야함 ㅇ.ㅇ 

iterateor

Posted 2012. 8. 13. 22:21

컨테이너 내부의 요소를 순회(traversing)하는 방법을 캡슐화한 객체. 현재 가리키는 요소를 반환하는 *연산자->연산자 를 가지고 있으며 그 외의 연산자는 반복자의 종류에 따라 다름.(iterator, reverse_iterator, const_iterator, const_reverse_iterator). 반복자는 클래스 템플릿이며 컨테이너마다 특화되어 있는 자료구조를 선형적으로 다룰수 있게 해준다.

(무효화 : 반복자가 가리키는 원소에 대한 참조가 정산적인 동작을 보장할 수 없게 되는경우)

 

반복자는 컨테이너의 특정 위치를 가르키고있음. Pointer와 같이 연산자를 사용할 수 있음(연산자 오버로드 되어있음)

operator* : 현재

operator ++ : 다음

operator -- : dlwjs

operator !=, == : 같은지 아닌지

operator = : 반복자를 할당

 

pointer와 다른것이 없어보이지만 iterater는 복잡한 컨테이너를 순회할수 있는 스마트 포인터임.

 

반복자는 후위연산보단 전위연산이 성능이 좋음(후위는 반복자의 이전값을 반환하기 때문에 임시로 객체가 생김)

 

con::iterator            : 원소들을 읽기/쓰기 가능

con::const_iterator   : 읽기 전용(const)

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

STL 동적 할당 해제  (0) 2012.08.13
containers  (0) 2012.08.13
algorithm  (0) 2012.08.13
STL 이란 ?  (0) 2012.08.13

vector-소스 한개

Posted 2012. 8. 13. 22:20

#include <vector>

#include <iostream>

 #include <cstring>

using namespace std;

 

void MainMenu();

int SearchData();

 

typedef struct PersonInfo{
 char Name[20];
 int Age;
 char ID[20];
 char PW[20];
}Person;

 

void main()

{

 vector<Person> Data;

// iter를 선언해도 되지만 배열은 바로 접근ㅇ ㅣ가능하기에 그냥 사용 

 while(1)

{

MainMenu();
cin >> Select;

if(Select == 1)

{

Person temp;
cout << "이  름 : ";
cin >> temp.Name;
cout << "나  이 : ";
cin >> temp.Age;
cout << "I    D : ";
cin >> temp.ID;
cout << "P    W : ";
cin >> temp.PW;
Data.push_back(temp);

}
  else if(Select == 2){
   for(int i = 0 ; i < Data.size() ; i++){
    cout << "이 름 : " << Data[i].Name << endl;
    cout << "나 이 : " << Data[i].Age << endl;
    cout << "I   D : " << Data[i].ID << endl;
    cout << "P   W : " << Data[i].PW << endl;
   }
  }
  else if(Select == 3){
   if(SearchData() == 1){
    char name[20];
    cout << "이름 입력 : ";
    cin >> name;
    for(int i = 0 ; i < Data.size() ; i++){
     if(!strcmp(name, Data[i].Name))
      Data.erase(Data.begin() + i);
    }
   }
   else{
    char id[20];
    cout << "I  D 입력 : ";
    cin >> id;
    for(int i = 0 ; i < Data.size() ; i++){
     if(!strcmp(id, Data[i].ID))
      Data.erase(Data.begin() + i);
    }
   }
  }
  else if(Select == 4){
   if(!Data.empty())
    Data.clear(); // Data.erase(Data.begin(), Data.end());
   else
    cout << "데이터가 없습니다" << endl;
  }
  else if(Select == 5) break;
 }

 

}

 

void MainMenu()

{

 cout << "--------------" <<endl;
 cout << "     vector     " << endl;
 cout << "--------------" <<endl;
 cout << "1.입      력" << endl;
 cout << "2.출      력" << endl;
 cout << "3.검색 삭제" << endl;
 cout << "4.전체 삭제" << endl;
 cout << "5.종     료" << endl;
 cout << "--------------" <<endl;
 cout << "선     택 : ";

}

 

 int SearchData()

{

 int i;
 cout << "검색할 목록 선택" << endl;
 cout << "1.이 름  2.I  D" << endl;
 cout << "선택 : ";
 cin >> i;

 return i;

}

'C++ > STL-vector' 카테고리의 다른 글

vector  (0) 2012.08.13

vector

Posted 2012. 8. 13. 22:20

벡터(std::vector)

  1. 동적 배열 구조를 c++로 구현한 것.
  2. c의 배열(빠른 랜덤 접근이 가능)처럼 되지만 자동으로 배열의 크기조절과 객체의 추가와 삭제가 가능하다.
  3. 한번에 한 타입만 저장이 가능. 요소에 접근하거나 앞 뒤 또는 요소를 추가하거나 삭제할 수 있다.

     

단 점

1.무조건 선형적으로 만들기때문에 저장공간보다 많은 양의 데이터를 추가시킬 경우에는 현재 보유하고 있는 메모리의 두 배 만큼을 할당하기 때문에 단순한 추가 할당으로는 선형적인 공간을 만들어내지 못하는 경우가 있다. 이럴때 선형적인 다른 공간에 모든 원소를 하나하나 복사하기 때문에 속도가 느려진다.

지금은 기존 표준에서 벡터의 길이가 늘어날 경우 부하가 큰 복사가 아닌, 메모리 상에서의 이동이 이뤄져 성능에 비약적인 발전이 이뤄졌다.

2. 중간 삽입 삭제가 불가능

 

벡터는 삽입삭제는 느리지만 검색은 빠르다.... ☆

 

가능한점

  1. 크기변경
  2. 순차 접근
  3. 랜덤 접근

 

원본> http://blog.naver.com/bravedog/100005052459

■ vector의 생성자와 소멸자

동작

효과

vector<Elem> c

원소 원이 빈 vector를 생성한다

vector<Elem> c1(c2)

같은 타입의 다른 vector를 복사하여 생성한다(모든 원소들은 복사된다)

vector<Elem> c(n)

디폴트 생성자에 의해서 생성되는 n개의 원소와 함깨 vector를 생성한다

vector<Elem> c(n,elem)

elem 원소의 n개의 복사본으로 vector를 초기화하여 생성한다

vector<Elem> c(begn,elem)

[beg,end) 범위의 원소로 vector를 초기화하여 생성한다

c.~vector<Elem>()

모든 원소들을 파괴하고 메모리를 해제한다


 

■ vector의 수정하지 않는 동작들

동작

효과

c.size()

실제 원소의 개수를 반환한다

c.empty()

컨테이너가 비어있는지를 판단한다 (size()==0와 동일하나 더 빠르다).

c.max_size()

컨테이너가 가질 수 있는 최대 원소의 개수를 반환한다.

capacity()

재할당 없이 가질 수 있는 최대의 원소 개수를 반환한다

reserve()

용량이 충분하지 않다면 용량을 증가시킨다

c1 == c2

c1과 c2가 같은지 판단한다

c1 != c2

c1과 c2가 다른지 판단한다 ( !(c1==c2)와 동일하다 ).

c1 < c2

c1이 c2보다 작은지를 판단한다

c1 > c2

c1이 c2보다 큰지를 판단한다( c2<c1과 동일하다 ).

c1 <= c2

c1이 c2보다 작거나 같은지를 판단한다 ( !(c2<c1)와 동일하다 ).

c1 >= c2

c1이 c2보다 크거나 같은지를 판단한다 ( !(c1<c2)와 동일하다 ).


 

■ vector의 할당 관련 동작

동작

효과

c1 = c2

c2의 모든 원소들을 c1에 할당한다

c.assign(n, elem)

elem 원소의 n개의 복사본을 할당한다

c.assign(beg, end)

[beg,end) 범위의 원소를 할당한다

c1.swap(c2)

c1과 c2의 데이터를 교체한다.

swap(c1,c2)

동일하다(전역 함수).


 

■ vector의 원소의 직접적인 액세스

동작

효과

c.at(idx)

인덱스가 idx인 원소를 반환한다

(만약 idx가 범위를 벗어났다면 범위 에러 예외를 발생시킨다)

c[idx]

인덱스가 idx인 원소를 반환한다(에러 검사를 하지 않는다)

c.front()

첫 번째 원소를 반환한다(원소가 있는지 검사하지 않는다)

c.back()

마지막 원소를 반환한다(원소가 있는지 검사하지 않는다)


 

■ vector의 반복자 함수들

동작

효과

c.begin()

첫 번째 원소를 가리키는 랜덤 액세스 반복자를 반환한다

c.end()

맨 마지막 원소 뒤를 가리키는 랜덤 액세스 반복자를 반환한다

c.rbegin()

역방향에서 첫 번째 원소의 역방향 반복자를 반환한다

c.rend()

역방향에서 마지막 원소 뒤를 가리키는 역방향 반복자를 반환한다


 

■ vector 원소의 삽입 및 제거 동작

동작

효과

c.insert(pos,elem)

반복자 pos위치에 elem의 복사본을 삽입한다

그리고 새로운 원소의 위치를 반환한다

c.insert(pos,n,elem)

elem의 n개의 복사본을 반복자 pos 위치에 삽입한다. 반환값은 없다.

c.insert(pos,beg,end)

[beg,end) 범위의 모든 원소들을 복사하여 반복자 pos 위치에 삽입한다.

반환값은 없다.

c.push_back(elem)

끝부분에 elem의 복사본을 추가한다.

c.pop_back()

마지막 원소를 제거한다(제거된 원소를 반환하지 않는다.)

c.erase(pos)

반복자 pos 워치의 원소를 제거한다. 그리고 다음 원소의 위치를 반환한다.

c.erase(beg,end)

[beg,end)범위의 모든 원소들을 제거한다. 그리고 다음 원소의 위치를 반환

c.resize(num)

원소의 개수를 num개로 변경한다

(만약 size()가 증가된다면, 새로운 원소들은 그들의 디폴트 생성자에 의해서 생성된다.)

c.resize(num,elem)

원소의 개수를 num개로 변경한다

(만약 size()가 증가된다면, 새로운 원소는 elem의 복사본이다).

c.clear()

모든 원소들을 제거한다(빈 컨테이너로 만든다).

'C++ > STL-vector' 카테고리의 다른 글

vector-소스 한개  (0) 2012.08.13
« PREV : 1 : 2 : 3 : NEXT »