Lyn
조회 수 37097 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

1. 자동업데이트(이거 이슈 거의 무조건 생기는거 같다..)


2. 서버인증


3. 패킷 암호화


4. 접속유지체크(이걸 프레임워크단에 넣어야하나 어플단에서 구현해야하나...)


5. 일부 알고리즘을 분리해서 인증없이 실행 안되도록.


6. 크래시 덤프



?

Lyn
조회 수 42323 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

XMarks : 북마크 동기화


Fire Gesutrs : 제스쳐


FasterFox : 속도 증가(캐시 이용)

?

Lyn
조회 수 39256 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Non-ASCII_Characters


번역중


헤더파일

  - 중복방지를 위한 헤더가드 : 모든 헤더는 중복 include 를 막기 위한 헤더가드를 가진다. 이는 <PROJECT>_<PATH>_<FILE>_H_ 의 포맷으로 만들어져있어야 한다

  - 헤더파일 의존성 : 번역중

  - 인라인 함수 : 10줄 혹은 그보다 작은 함수에만 사용한다.

  - -ini.h 파일 : 복잡한 인라인함수를 만들어야 할 때 ~ini.h 형태를 사용한다

  - 함수 파라메터 순서 : 함수 파라메터는 입력파라메터가 출력 파라메터보다 먼저 온다



?

Lyn
조회 수 37663 추천 수 0 댓글 0
Atachment
첨부 '1'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

boost  shared_ptr 은 편한 놈이지만..

문제가 생기는 상황이 몇 가지 있다 있다그 중 하나 바로 객체 내부에서 전역 함수(혹은 다른 class 의 함수)를 호출 할 때 this 를 넘기는 문제인데

 

왜나면 아래와 같은 코드가 안되기 때문이다.

 

shared_ptr과 포인터형은 서로 대입이 되지 않기 때문에 위와 같은 코드는 컴파일 에러를 뱉는다그럼 아래와 같이 고치면 어떨까.

 

 

this 를 shared_ptr<SPtrTestthisptr(this);

로 변환 해서 넘겻다.

 

이렇게 하면.

SPtrTest::Operation이 끝날때와 Func 가 끝날 때 2 destructor 가 호출 되게 되어 에러가 난다.

이걸 방지하는 방법은 자기 자신의 shared_ptr 을 레퍼런스 카운트 문제가 생기지 않도록(this 를 넘길 때도 레퍼런스 카운터가 증가 하는하는 것이다.

 

즉 boost::enable_shared_from_this<T> 를 상속 받은 class 를 만드는 방법이다.

boost::enable_shared_from_this<T> 를 상속 받은 뒤 shared_from_this() 를 호출 하면 자기 자신의 shared_ptr 을 리턴 해 준다.

 

그럼 아래와 같이 된다

#include <boost/shared_ptr.hpp>

#include <cstdio>

 

using namespace boost;

 

class SPtrTest;

 

void Func(shared_ptr<SPtrTestsp);

 

class SPtrTest

{

public:

        int var1;

        SPtrTest()

        {

               printf("Constructor\n");

        }

        ~SPtrTest()

        {

               printf("Destructor\n");

        }

        void operation()

        {

              

               Func(this);

        }

};

 

void Func(shared_ptr<SPtrTestsp)

{

        sp->var1++;

        printf("%d\n"sp->var1);

};

 

int _tmain(int argc_TCHARargv[])

{

 

        shared_ptr<SPtrTesttestclass(new SPtrTest);

        testclass->var1 = 0;

        testclass->operation();

              

        return 0;

}

 

이렇게 하면 아무 문제 없이 작동이 가능하다.

 

 

 

Ps. 특히 조심해야 할 것은..

shared_ptr<SPtrTestthisptr(this); 를 여러 번 생성 한다고 레퍼런스 카운터가 증가하는 것은 아니다레퍼런스 카운터의 증가는 변수끼리의 대입에 의해서만 증가할 뿐저런 선언은 카운터1짜리 변수를 여러 개 늘려 에러를 내게 할 뿐이다.

#include <boost/shared_ptr.hpp>

#include <cstdio>

 

using namespace boost;

 

class SPtrTest;

 

void Func(shared_ptr<SPtrTestsp);

 

class SPtrTest

{

public:

        int var1;

        SPtrTest()

        {

               printf("Constructor\n");

        }

        ~SPtrTest()

        {

               printf("Destructor\n");

        }

        void operation()

        {

               shared_ptr<SPtrTestthisptr(this);

               Func(thisptr);

        }

};

 

void Func(shared_ptr<SPtrTestsp)

{

        sp->var1++;

        printf("%d\n"sp->var1);

};

 

int _tmain(int argc_TCHARargv[])

{

 

        shared_ptr<SPtrTesttestclass(new SPtrTest);

        testclass->var1 = 0;

        testclass->operation();

              

        return 0;

}




#include <boost/shared_ptr.hpp>

#include <boost/weak_ptr.hpp>

#include <boost/smart_ptr/enable_shared_from_this.hpp>

#include <cstdio>

 

using namespace boost;

 

class SPtrTest;

 

void Func(shared_ptr<SPtrTestsp);

 

class SPtrTest : public boost::enable_shared_from_this<SPtrTest>

{

public:

        int var1;

        SPtrTest()

        {

               printf("Constructor\n");

        }

        ~SPtrTest()

        {

               printf("Destructor\n");

        }

        void operation()

        {

               Func(shared_from_this());

        }

};

 

void Func(shared_ptr<SPtrTestsp)

{

        sp->var1++;

        printf("%d\n"sp->var1);

};

 

int _tmain(int argc_TCHARargv[])

{

 

        shared_ptr<SPtrTesttestclass(new SPtrTest);

        testclass->var1 = 0;

        testclass->operation();

              

        return 0;

}

?

Lyn
조회 수 34290 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

==여기서부턴 내 개인적인 생각이니... 할말있으면 태클 거는건 좋다.==

 

프로그래머에게 앱스토어의 유행이란 과연 무엇일까..

 

 

혹자는 이렇게 말할지도 모른다. 개인 개발자들에게 대박의 기회를 주었다고...

물론 난 대박이란 말을 좋아하지 않는다. 왠지 운으로 된 것이라는 느낌을 강하게 주기때문에. 하지만 여기선 딱히 쓸 말이 없는 거 같아 그냥 대박이라 표현하기로 하자. 내 짧은 어휘력에 저주를 한번 보내주는 것은 좋다.

 

이 얘기는 물론 대박을 친 사람이 있다는 얘기는 아니다.

난 아직까지 앱스토어에서 대박친 사람을 본 적이 없다. 기껏해야 중박정도랄까. 애시당초 큰 돈을 벌 수 있는 시스템이 아니다.

그리고 앱스토어는 이제 개인 한두명일 달라붙을 수 있는 시장이 아니라 규모를 갖춘 팀이 아니면 승부를 하기 힘든 시장이다.

 

 

내가 말하고싶은건 뭐냐...

프로그래머에게 앱스토어는 저주나 다름없다는 것이다. 적어도 한국에서는..

공짜 혹은 비싸봐야 천원내지 수천원 이건 무슨 의미냐. 프로그램은 "싸다" 라는 인식을 사람들에게 박아준 것 이외엔 아무것도 아니다.

프로그램은 엄청난 인건비를 소모 해야만 만들 수 있다. 그런것이 천원 이천원에 팔린다는것은 가치를 우리 스스로 무시한 것 외에 아무것도 아니다.

 

프로그래머들의 재미있는 장난감이 될 수는 있다 앱스토어가. 하지만 재미삼아 만들었으면 그것으로 끝내라. 그걸 싼값에 공개하는건 우리 스스로 가치를 깎아먹는 것 밖에는 안된다. 

 

중급개발자가 월급이 300만원이라고 하면 시간당 2만원을 버는셈인데... 그것을 1달러(대충 1000원으로 치자) 에 판다고 하자.

아이폰 앱스토어에서 100개 이상 팔리는 어플의 비율이 10% 정도라고 하는데... 상위 10%의 어플을 만들어 냇다고 치자. 그럼 10만원을 버는 셈이다. 당신이 그걸 5시간 이내에 완성한 것이 아니라면 완전한 손해라고 밖에 할 수 없다.

?

Lyn
조회 수 39601 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

볼포 모임에서도 이런저런 얘기 하다 나온거지만...

델파이 / C++빌더 초보들은 웃기는 특징을 하나 가지고 있다.



뭔가 하다가 안된다.

그럼 이렇게 생각한다. '아 이게 델파이의 한계인가'


.... 웃긴다.

그런사람들이 VC를 하면서 똑같은 문제에 부딛히면 이렇게 생각한다 '아 내가 뭘 잘못한게 있나보다'

... 진짜 웃긴다




뭔가 하려고 할때 개발툴 자체에 한계가 있는 경우는 드물다.

(물론 VM 의 한계, Native의 한계 등이 있지만... 이 경우는 애초에 언어선택자체가 잘못된거니까 제쳐두자.)

개발툴 탓하기 전에 자신의 실력을 한번쯤 돌아보길.





근데... 난 델파이 프로그래머 아니잖아.... 안될거야 아마

?

Lyn
조회 수 39039 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

1. Visual Studio 2008  2010 + Intel C++ 11.1 12.1 // 개발툴.

    - Visual Assist // VS Add-on


2. Delphi 2007, Delphi 2010 XE2 //개발툴

    -Castailla // Delphi Add-on


3. VirtualBox 

가상머신 가벼워서 자주 이용


3. VMWare

VirtualBox 가 불안해서 VMWare로 완전 이사


4. TeraCopy

쉘확장. 윈도우의 파일복사/이동 기능을 확장해줌.

복사중 일부분 취소, 일시정지, Copy<->Move 전환기능 등


걍 Total Commander 쓰기로 했다. 윈도7에선 TeraCopy가 너무 느리다.


5. Microsoft Office 200 2010 // 문서


6. Total Commander

다기능 툴이지만 파일이름변경, FTP 등의 기능을 주로 이용


7. 구글 크롬

    - IE Tab

    - Gesture

초고속 웹 브라우저


8. Beyond Compare 3

파일비교 솔루션. 개발보조툴


9. Tortoise SVN, TortoiseHG

SVN 프론트엔드. 개발보조툴


10. Warcraft III, Startcraft II

게임


11. NateOn, Google Talk, MSN

메신저

?

Lyn
조회 수 40771 추천 수 0 댓글 1
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

- 2010.1.3 지금 이걸 계속 써야 하나 말아야하나 고민중이다. 단돈 몇만원이 아까운게 아니라면 Beyond Compare 사서 써라. 진리다. 비교할 의미자체를 모르겠다(단. 3Way Marge 는 내가 쓰지 않아 잘 모른다)

  2011.11.22 2년사이에 많이 바뀌어서 내용을 추가


[파일비교]

Araxis Merge :

  달라진 부분을 보여주는 가이드라인이 너무 작아서 눈에 띄지 않음.

  단 선으로 바뀐 부분을 보여주기에 매우 많은 길이의 코드가 연속적으로 달라졋을 경우 직관적.

 

Beyond Compare :

  바뀐 부분을 영역색, 글씨색으로 나누어 보여주어서 보기 편함.

  달라진 부분을 보여주는 가이드라인의 길이가 화면크기와 별도로 나타나 직관적이지 않음.

  바뀐 부분이 한 줄의 일부, 아니면 몇줄 이하일 경우 직관적으로 보이나, 바뀐 부분의 길이가 길 경우, 특히 한페이지가 넘어 갈 경우는 보기가 상당히 불편하다.

 

Ultra Compare : 

  돈내고 쓸 가치가 없다. 알고리즘이 개판이다.


Kdiff

  한글 지원이 쓰레기 of 쓰레기라 배제


WinMerge

  제작자는 이 UI로 정말 코드 비교를 할수 있는지 한번 묻고싶다


[폴더비교]

Araxis Merge :

  폴더 비교 창이 매우 난잡하여 보기힘들다.

  필터가 매우 단순

  최신버전에서 필터 기능이 강력해졋다

Beyond Compare :

  알아보기 쉽게 색으로 잘 표시되어 있다.

  필터링 기능이 매우 막강하다. 특히 프로그래머가 jpg, bmp 파일을 Compare 툴로 보는것은 의미가 없는데 필터 옵션에서 아주 간단하게 걸러낼 수 있다.


[기타기능]

Araxis Merge:

  소스비교, 바이너리 비교. 그 이상의 잡기능은 없다

Beyond Compare:

  Mp3비교, 이미지 비교 등등 굉장히 다양한 포맷을 비교하는 기능을 제공한다.


[가격]

Araxis Merge :

  비싼 값에 비해, 밥값을 못한다.

  이제 밥값정돈 한다. 그래도 비싸다

Beyond Compare :

  유료이긴 하지만 비싸지 않고, 이 가격대에 이정도 툴이면 매우 훌륭하다.

 

KDiff, WinMerge : 

  싼게 비지떡이다. 정말 돈이 없다면 그때나 고민해 보자


 

PS. DiffMerge, AcroDiff 등 비교 예정

?

2009.08.19 03:08

C++ new 연산자의 진실

Lyn
조회 수 57718 추천 수 0 댓글 2
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

new 연산자의 진실

 

C++에서는 메모리를 할당할 때 new 연산자를 사용합니다.

그리고 이 new 라는 연산자는 오버로딩이 가능합니다. 그럼 과연 이 new 의 정체는 뭘까요?

new 를 호출하면 실제로는 malloc 이 내부에서 다시 호출 된 다는 것은 일단 다 안다고 가정하고 넘어가겠습니다.

 

첫 코드 나갑니다. 연산자 new 를 오버로딩 한 경우입니다.

#include <stdio.h>

#include <stdlib.h>

 

class Test

{

public:

           int a;

 

           void* operator new(size_t size)

           {

                     printf("한 개 할당중\n");

                     Test* temp = (Test*)malloc(size);

                     return temp;

           }

           Test()

           {

                     printf("Test Constructor\n");

           }

};

int main()

{

           Test* t1;

 

           t1 = new Test;

 

           system("pause");

           return 0;

}

 

new 에는 size_t 형태의 파라메터가 하나 존재합니다. 이 파라메터로 할당 해야 할 크기를 알려줍니다. 단순히 그 크기로 메모리를 할당 하고 리턴 만 하엿습니다.

 

실행결과는 아래와 같습니다.

 

image1.png

 

우리는 부른적도 없는 생성자가 호출되었습니다. new 가 단순히 메모리 할당만 하도록 오버로딩 하엿는데요. 여기서 new 는 실제로는 오버로딩이 되지 않았다고 할 수 있겠습니다. 뭔가 수상하군요. 디스어셈블 해 보았습니다.

 

image2.png

 

이런 우리는 new 를 호출했을 뿐인데 실제로는 operator new 라는 함수와 생성자를 따로따로 호출 하고 있었네요. 그럼 우리가 수정한 것은 operator new 라는 함수 일 뿐 new 연산자 자체가 아니라는것을 알 수 있습니다.

 

심지어 윗줄에서는 할당 할 메모리 크기를 스택에 집어넣어주는 친절함(?) 까지 엿볼 수 있군요. Pop 이 호출부위 아래에 존재한다는 것은 operator new cdecl 방식으로 call 되고 있다고 짐작 할 수 있겠습니다.

 

그럼 new 는 단지 operator new 와 생성자를 호출 하고 있을 뿐이라면 이 두 함수를 따로 따로 호출하는것도 가능하지 않을까요? 다음과 같은 코드를 짜 보았습니다.

#include <stdio.h>

#include <stdlib.h>

 

class Test

{

public:

           int a;

 

           void* operator new(size_t size)

           {

                     printf("한 개 할당중\n");

                     Test* temp = (Test*)malloc(size);

                     return temp;

           }

           Test()

           {

                     printf("Test Constructor\n");

           }

};

int main()

{

           Test* t1;

 

           t1 = (Test*)Test::operator new(sizeof(Test));

           t1:Test();

 

           system("pause");

           return 0;

}

 

그리고 실행 해 보았습니다.

 

image3.png

 

이런 완전히 똑같군요.

 

 

그럼 이렇게 결론 내릴 수 있을까요? new 연산자는 operator new 함수를 호출 한 후, 생성자를 호출 해 주는 연산자이다.

 

그런데 이게 또 아닌거 같습니다. 왜냐면 이 두 함수에는 VMT(Virtual Methor Table) 을 생성 해 주는 부분이 없거든요. 가상함수가 한 개 이상 존재하고 상속관계가 있는 클래스(상속 받았던 상속 했던) 에는 반드시 VMT의 포인터가 존재합니다. 그럼 이 VMT는 언제 등록되었을까요? 살짝 코드를 고쳐보았습니다.

 

#include <stdio.h>

#include <stdlib.h>

 

class Test

{

public:

           int a;

 

           void* operator new(size_t size)

           {

                     printf("한 개 할당중\n");

                     Test* temp = (Test*)malloc(size);

                     return temp;

           }

           Test()

           {

                     printf("Test Constructor\n");

                     func();

           }

 

           virtual void func()

           {

                     printf("Test::func()\n");

           }

};

 

class Test2 : public Test

{

           virtual void func()

           {

                     printf("Test2::func()\n");

           }

};

int main()

{

           Test* t1;

 

           t1 = new Test2;

 

           system("pause");

           return 0;

}

 

 

생성자에서 func라는 가상함수를 호출 하고 있습니다.

우리는 Test2를 생성하였으므로 Test2::func() 가 출력 될 거라고 기대 할 수 있겠습니다. 결과를볼까요?

 

image4.png

 

어라 뭔가 이상합니다. Test::func() 가 출력되었네요. 이게 어찌 된 일일까요?

그 이유는 생성자를 호출 하는 시점에서는 VMT의 포인터가 제대로 등록 되지 않기 때문에, 가상함수 본래의 역할을 제대로 하지 못하는 겁니다. 디스어셈블 한 코드를 보겠습니다.

 

image5.png

 

생성자를 호출 한 다음에도 추가적인 작업을 하고 있습니다.

그 중 빨간 네모로 표시 된 부분이 가상함수가 없을때는 존재하지 않던 부분입니다.

즉 저 부분에서 VMT포인터를 추가하는 작업을 하고 있다고 생각 할 수 있겠습니다.

 

이제 new 의 진실이 밝혀졋군요.

new 연산자를 호출하면

 

1.     메모리 할당을 위해 operator  new 함수를 호출한다

2.     생성자를 호출한다

3.     VMT를 등록해 준다

 

3가지 과정으로 new 의 역할은 모두 종료됩니다.

쉽고 편하게 쓰던 연산자가 참 하는 일도 많네요 : )

 

그럼 또 다른 언어인 Delphi 의 경우는 어떨까요?

 

program Project2;

 

{$APPTYPE CONSOLE}

 

uses

  SysUtils;

 

type

  Test = class

  public

    a : Integer;

 

    procedure func;virtual;

    constructor Create;

  end;

 

  Test2 = class(Test)

  public

    procedure func;override;

  end;

 

constructor Test.Create;

begin

  func;

end;

 

procedure Test.func;

begin

  WriteLn('Test.Func');

end;

 

procedure Test2.func;

begin

  WriteLn('Test2.Func');

end;

 

var

  T : Test;

begin

  T := Test2.Create;

  ReadLn;

end.

 

출력 결과는 아래와 같습니다.

image6.png

 

Delphi는 생성자 호출 시점이 VMT 생성 시점보다 뒤입니다.

Delphi 에서는 생성자 내에서 가상함수를 호출하더라도 정상적으로 작동합니다.

?

Lyn
조회 수 42563 추천 수 0 댓글 0
Atachment
첨부 '2'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

tokenizer 는 말 그대로 Token 단위로 문자열을 쪼개는 기능을 한다.

토큰은 사전상의 의미로는 버스탈때 내는 동전 비슷한것 (....) "의미를 갖는 최소한의 문자열" 의 의미를 갖는다. 당연히 여기에서는 후자의 의미다.

 

c 라이브러리에서는 strtok 이 제공 되지만 이는 thread 에서 사용 할 수 없다(전역변수를 사용 하기 때문에)

VCL 에서는 TStringList 가 비슷 한 기능을 제공 하고 MFC에서도 기억은 안나지만 (...) 비슷한 기능을 제공 한다.

 

뭐 항상 이야기 하는 거지만 boost 는 플랫폼을 가리지 않는 다는 것 만으로도 충분한 가치가 있다 : )

그럼 간단하게 사용 예제만 보도록 하자.

 

첫번째 예제 소스 나간다.

 

#include<boost/tokenizer.hpp>

#include<string>

#include<iostream>

 

using namespace std;

using namespace boost;

 

typedef tokenizer<char_separator<char> > TOKC;

int main(int argc, _TCHAR* argv[])

{

         string BorlandUser = "Lyn/Yull/TestCode/Imp//bkyang/4000king/RyuJT/gilgil/esniper/civilian";        

         char_separator<char> sep("/",""); 

        

         TOKC tok(BorlandUser, sep);       

 

         for (TOKC::iterator i = tok.begin(); i != tok.end(); ++i)

         {

                  cout << *i << endl;

         }

         return 0;

}



 

문자열을 '/' 단위로 쪼개기로 하자.

그럼 결과는 아래와 같다.

 

1.png

잘 쪼개 졋다. 그런데 한가지 주의해서 볼 점이 있는데 빈 토큰은 나타나지 않는 다는 것이다.

빈 토큰도 살리기 위해서는 separator 의 생성자에 keep_empty_tokens 옵션을 주면 된다.

 

두번째 예제를 보자

#include<boost/tokenizer.hpp>

#include<string>

#include<iostream>

 

using namespace std;

using namespace boost;

 

typedef tokenizer<char_separator<char> > TOKC;

int main(int argc, _TCHAR* argv[])

{

         string BorlandUser = "Lyn/Yull/TestCode/Imp//bkyang/4000king/RyuJT/gilgil/esniper/civilian";        

         char_separator<char> sep("/","", keep_empty_tokens);

        

         TOKC tok(BorlandUser, sep);       

 

         for (TOKC::iterator i = tok.begin(); i != tok.end(); ++i)

         {

                  cout << *i << endl;

         }

         return 0;

}

 

2.png

 

빈 토큰도 구해진 것을 볼 수 있다 : )

참여해 주신 볼랜드(코드기어? 엠바카데로?) 유저분에게 심심한 감사를 표하면서 끝내겠다 (__)



PS. 유니코드 일 경우 typedef tokenizer<char_separator<wchar_t>, wstring::const_iterator, wstring> TOKC; 와 같이 선언하는것이 편리하다

?

Lyn
조회 수 41914 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

이번엔 공백 처리 함수들이다. 로그인할때 아이디 처리라던지에 써먹은 기억이 있다 : )


#include <cstdio>

#include <string>

#include <boost/algorithm/string.hpp>

 

using namespace boost;

using namespace std;

 

int _tmain(int argc, _TCHAR* argv[])

{

        string str1 = "   I love Lyn!      ";

        string str2;

        trim(str1); //양옆의공백을다제거한다.

        printf("trim : %s\n", str1.c_str());

 

        str1 = "   I love Lyn       ";

        str2 = trim_copy(str1); //양옆의공백을다제거하되원본을변경하지않고새로운문자열을리턴

        printf("trim_copy : %s, %s\n", str1.c_str(), str2.c_str());

 

        str1 = "#######   I love Lyn       #######";

        trim_if(str1,is_any_of("#")); //제거할문자를직접지정해서제거한다.

        printf("trim_if-1 : %s\n", str1.c_str());

 

        str1 = "!@#!@#I love Lyn!@#!@#";

        trim_if(str1,is_any_of("!@#")); //제거할문자열의길이에는제한이없다!

        printf("trim_if-2 : %s\n", str1.c_str());

 

        str1 = "   I love Lyn       ";

        trim_left(str1); //왼쪽의공백을제거한다.

        printf("trim_left : %s\n", str1.c_str());

       

        //물론trim_left_copy, trim_left_if, trim_right, trim_right_copy, trim_right_copy_if 등등.. 있을함수는다있다.

        //여기서는몇가지만소가했지만네이밍규칙을보면다알수있을수준이다.

        return 0;

}

 

?

Lyn
조회 수 41627 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

이번엔 문자열 다루는 알고리즘 들이다.
C++ 기본 라이브러리에서 당연히 지원 해줄것 같은데 안해주는(...) 문자열 관련 함수들을 담고 있다.
첫번째로 대소문자 변경 기능만 살펴본다.

String 알고리즘은 원본을 변형하는 형태와, 원본을 보존하고 새로운 문자열을 리턴하는 두가지 형태로 지원되는점이 특징이다.

#include <string>

#include <boost/algorithm/string.hpp>

 

using namespace std;

using namespace boost;

 

int _tmain(int argc, _TCHAR* argv[])

{

        string str = "Hello Lyn!";

        string str2;

        printf("%s\n", str.c_str());

 

        to_upper(str); //모두대문자로바꾼다

        printf("%s\n", str.c_str());

        to_lower(str); //모두소문자로바꾼다

        printf("%s\n", str.c_str());

       

        str = "Hello Lyn!";

        str2 = to_upper_copy(str); //모두대문자로바꾸되원본을변형하지않고새로운문자열을리턴

        printf("%s %s\n", str.c_str(), str2.c_str());

        str2 = to_lower_copy(str); //모두소문자로바꾸되원본을변형하지않고새로운문자열을리턴

        printf("%s %s\n", str.c_str(), str2.c_str());

 

        return 0;

}

?

Lyn
조회 수 41367 추천 수 0 댓글 0
Atachment
첨부 '1'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

이번엔 lexical_cast 에 대해서 알아보자.
cast 란 이름에서 눈치챗겠지만 일종의 캐스팅 연산자(인 척 하는 함수) 이다.
string -> Integer 같은 상식적으론 말이 되지만 C++문법상으론 말이 안되는 일들을 처리한다.

일단 예제코드를 소개한다.
timer 에 관해서는
http://lunapiece.net/3795 를 참조해라

#include <boost/lexical_cast.hpp>

#include <cstdlib>

#include <string>

#include <boost/timer.hpp>

 

using namespace std;

using namespace boost;

 

string Number = "1024768";

 

void StrToIntAtoi()

{

        int num;

        for(int i=0;i < 1000000; ++i)

        {

               num = atoi(Number.c_str());

        }

        printf("atoi : %d\n", num);

}

void StrToIntStringStream()

{

        stringstream sst;

        int Num;

        for(int i=0;i < 1000000; ++i)

        {

               sst << Number.c_str();

               sst >> Num;

        }

        printf("StringStream : %d\n", Num);

}

void StrToIntLexicalCast()

{

        int num;

        for(int i=0;i < 1000000; ++i)

        {

               num = lexical_cast<int>(Number);

        }

        printf("LexicalCast : %d\n", num);

}

int _tmain(int argc, _TCHAR* argv[])

{

        timer t;

        printf("atoi 를이용한방법\n");

        t.restart();

        StrToIntAtoi();

        printf("%lf \n", t.elapsed());

 

        printf("StringStream 을이용한방법\n");

        t.restart();

        StrToIntStringStream();

        printf("%lf \n", t.elapsed());

 

        printf("lexical_cast 를이용한방법\n");

        t.restart();

        StrToIntLexicalCast();

        printf("%lf \n", t.elapsed());

 

        return 0;

}

 

.....

예제코드 자체는 별 문제가 없었으리라 본다. 준비작업도 필요없고 간단하게 쓸 수 있어서 참 좋아보이기는 한다.
하나의 함수로 이런저런 캐스팅을  다 할수 있으니 다형성도 뛰어나다.
그러나 치명적인 문제가 딱 하나 있는데...

 

 

바로 이거다 속도 =_=;

stringstream 에 비해 약 10배, atoi 에 비해선 대략 50배 가량 느리다 =_=;; 편의성을 위해서 가끔 쓰는정도라면 몰라도 자주 반복되는 루틴에서는 쓰지 않아야 하겠다.

?

Lyn
조회 수 36714 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

multi_array는 다차원 정적배열을 지원하는 클래스이다.
이를 이용하는 다른 방법은 std::tr1::array 를 중첩해서 사용 하는 방법이 있는데, 이것을 좀 더 편하게 확장했다고 보면 되겠다.

std::tr::array에 관한 내용은 아래 링크를 참조해라
http://lunapiece.net/Article/476

 

아래는 multi_array와 중첩된 array에 관한 예제코드이다. 이것도 별 내용이 없다보니 그냥 코드 보여주는걸로 끝낸다.

 

#include "stdafx.h"

#include <array>

#include <multi_array.hpp>

#include <cstdio>

 

using namespace boost;

 

int _tmain(int argc, _TCHAR* argv[])

{

        //TR1Array를이용한Static Array of Array 구현

        printf("std::tr1::array<std::tr1::array<int,20>, 10>\n");

        std::tr1::array<std::tr1::array<int,20>, 10> Stdarr; //int[10][20] 선언

        //10*20인데선언시에는숫자가반대로씌여지므로헤깔린다!

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

        {

               for(int j = 0;j < 20; ++j)

               {

                       Stdarr[i][j] = 1;

               }

        }

 

        //boost::multi_array

        printf("multi_array 사용\n");

        multi_array<int, 2> MultiArray(extents[10][20]);

        //int2차원배열[10][20]을선언. 템플릿인자가Type 과차원을나타냄.

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

        {

               for(int j = 0;j < 20; ++j)

               {

                       MultiArray[i][j] = 2;

               }

        }

       

        printf("multi_array range 조정\n");

        //Pascal 처럼배열의인덱스를변형할수있는기능을제공한다.

        typedef multi_array<int, 2>::extent_range range; //이름이너무길어서ㅡ.

        multi_array<int, 2> MultiArray2(extents[range(1,4)][range(20,40)]);

        //Pascal 과비교하면Array [1..4-1] of Array[20..40-1] of Integer 라고할수있겠다.

        for (int i = 1; i < 4 ; ++i)

        {

               for(int j = 20;j < 40; ++j)

               {

                       MultiArray2[i][j] = 2;

               }

        }

        return 0;

}

 

 

 

?

Lyn
조회 수 44172 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

이번에는 timer 클래스이다.
단순히 시간을 재는데 이용 할 수 있는 클래스로 알고리즘 돌려놓고 시간측정하기 딱좋다.
아래 pool 예제 등에서도 이 timer 를 사용햇으면 더 편햇을텐데... 어쩌다 보니 이게 뒤로나왔다.

#include "boost/timer.hpp"

#include <cstdio>

#include <windows.h>

 

using namespace boost;

 

int main(int argc, char **argv)

{

        timer t; //생성시0으로초기화

        Sleep(1234);

        printf("%lf 초지남\n", t.elapsed());

        Sleep(1766);

        printf("%lf 초지남\n", t.elapsed());

        t.restart();//Restart 를이용하여다시초기화

        Sleep(512);

        printf("%lf 초지남\n", t.elapsed());

        return 0;

}

 

?

2009.05.11 22:44

[Boost 살펴보기] 2. any

Lyn
조회 수 36685 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

any 는 마치 스크립트 언어처럼 임의의 type을 가지는 변수를 만들 수 있다.
COM의 Varient 와도 비슷하다 하겠다.

하지만 이것을 언어수준에서 구현 해 놓았고, 다른 컨테이너와 매우 잘 맞물린다는것이 장점이라 하겠다.
vector 에 이런저런 잡데이터 쑤셔넣을때 참 좋더라
(당연히 오버헤드는 있다. 꼭 필요한 곳에만 사용하자!)

#include "stdafx.h"
#include <cstring>
#include <cstdio>
#include <boost/any.hpp>
#include <string>
#include <vector> 

using namespace boost;

using namespace std;

 

struct MyData

{

        int i;

        double d;

        MyData()

        {

        }

        MyData(const MyData& t) //Any의요구사항1 Copy Constructor

        {

               this->i = t.i;

               this->d = t.d;

        }

        MyData& operator =(const MyData &t) //Any의요구사항2 = operator overloading

        {

               this->i = t.i;

               this->d = t.d;

        }

};

int _tmain(int argc, _TCHAR* argv[])

{

        any Data;

        //값이비어있는지를확인하는방법

        if(Data.empty())

        {

               puts("Data 는비어있음!");

        }

        else

        {

               puts("Data 는비어있지않음!");

        }

        Data = 3.14; //실수리터럴의기본타잎은double

        Data = 3; //정수리터럴의기본타잎은Int

 

        //Data = "Hello!"; //에러.

        //any 에넣기위해선CopyConstructor = Operator Overloading 이필요하다.

        string str = "Hello";

        Data = str; //정상적

 

        //Any 에어떤타잎이들어있는지확인

        //type매소드로type 을확인후any_cast 연산자를사용하여캐스팅

        if(Data.type() == typeid(int))

        {

               printf("DataType : Int, Value : %d\n", any_cast<int>(Data));

        }

        else if(Data.type() == typeid(double))

        {

               printf("DataType : Double, Value : %lf\n", any_cast<double>(Data));

        }

        else if(Data.type() == typeid(string))

        {

               printf("DataType : string, Value : %s\n", any_cast<string>(Data).c_str());

        }

 

        //Vector Any 의복합사용예.

        printf("임의의타잎을담는Vector 선언하기\n");

        vector<any> AnyVector;

        MyData myData;

        myData.d = 5.12;

        myData.i = 5;

 

        AnyVector.push_back(3);

        AnyVector.push_back(3.14);

        AnyVector.push_back(myData);

 

        vector<any>::iterator it;

        for (it = AnyVector.begin(); it != AnyVector.end(); ++it)

        {

               if(it->type() == typeid(int))

               {

                       printf("Any Type : Int, Value : %d\n", any_cast<int>(*it));

               }

               else if(it->type() == typeid(double))

               {

                       printf("Any Type : Double, : %lf\n", any_cast<double>(*it));

               }

               else if(it->type() == typeid(MyData))

               {

                       printf("Any Type : MyData, Value : %d, %lf\n", any_cast<MyData>(*it).i, any_cast<MyData>(*it).d);

               }

        }

        return 0;

}

 

 

?

2009.05.11 22:04

[Boost 살펴보기] 1. pool

Lyn
조회 수 37062 추천 수 0 댓글 0
Atachment
첨부 '1'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

TR1에 포함되지 않은 Boost 의 다른 요소들 중 자주 쓸 만한 것들을 한번 눈여겨 볼까 한다

첫번째 예제는 Pool이다. 메모리를 미리 생성 해 놨다가 해제/생성이 반복 될 경우 미리 생성해 놓은 메모리를 재활용 하는데 유용하게 사용 할 수 있다. 개인적으로도 많이 구현해서 써 보았고 탁월한 메모리 성능을 보여 주는 방법이다.

아래에는 예제코드를 담았다. 예제코드에 있는 주석만으로도 충분히 사용 방법과 기능을 알 수 있을것이라 본다.
그림은 아래 코드를 실행한 속도 테스트 스크린샷이다(VS2008 Sp1 + Realese Mode)
일반적으로 메모리를 할당하는것 보다 훨신 빠름을 알 수 있다. 게다가 단편화의 문제도 적다.

#include "stdafx.h"

#include <iostream>

#include <cstring>

#include <boost/pool/pool.hpp>

#include <boost/pool/object_pool.hpp>

#include <windows.h>

 

using namespace std;

using namespace boost;

 

struct MyData

{

        int i;

 

        MyData()

        {

               puts("Constructor!");

        };

        ~MyData()

        {

               puts("Destructor!");

        }

};

struct MyData2

{

        int i;

};

 

MyData2** Array; //임시저장용

 

void UseNormalPool()

{

        pool<> pool(sizeof(MyData));

 

        MyData *p = (MyData*)pool.malloc();      

        //pool.free(p); //Free를하지않을경우pool이파괴될때pool에서생성한모든메모리가파괴됨.

}

 

void UseObjectPool()

{

        object_pool<MyData> pool;

 

        for (int i = 0; i < 1; ++i)

        {

               MyData *p = pool.malloc();

               //기본적으로같지만파괴시Destructor 가호출됨(주의: Constructor 는호출되지않음)

        }

}

void Test1NewAndDelete()

{

        for (int i = 0;i < 1000000; ++i)

        {

               MyData2* p = new MyData2;

               delete p;

        }

}

void Test1MallocAndFree()

{

        for (int i = 0;i < 1000000; ++i)

        {

               MyData2* p = (MyData2*)malloc(sizeof(MyData2));

               free(p);

        }

}

void Test1BoostPool()

{

        pool<> pool(sizeof(MyData));

        for (int i = 0;i < 1000000; ++i)            

        {

               MyData *p = (MyData*)pool.malloc();  

               pool.free(p);

        }

}

void Test2NewAndDelete()

{

        for (int i = 0;i < 1000000; ++i)

        {

               Array[i] = new MyData2;

        }

        for (int i = 0;i < 1000000; ++i)

        {

               delete Array[i];

        }

        for (int i = 0;i < 1000000; ++i)

        {

               Array[i] = new MyData2;

        }

        for (int i = 0;i < 1000000; ++i)

        {

               delete Array[i];

        }

}

void Test2MallocAndFree()

{

        for (int i = 0;i < 1000000; ++i)

        {

               Array[i] = (MyData2*)malloc(sizeof(MyData2));

        }

        for (int i = 0;i < 1000000; ++i)

        {

               free(Array[i]);

        }

        for (int i = 0;i < 1000000; ++i)

        {

               Array[i] = (MyData2*)malloc(sizeof(MyData2));

        }

        for (int i = 0;i < 1000000; ++i)

        {

               free(Array[i]);

        }

}

void Test2BoostPool()

{

        pool<> pool(sizeof(MyData2));

        for (int i = 0;i < 1000000; ++i)            

        {

               Array[i] = (MyData2*)pool.malloc();  

        }

        for (int i = 0;i < 1000000; ++i)            

        { 

               pool.free(Array[i]);

        }

        for (int i = 0;i < 1000000; ++i)            

        {

               Array[i] = (MyData2*)pool.malloc();  

               //Free후재할당을할경우이미생성된메모리가재사용됨

               //Free를하더라도실제메모리는파괴되지않음

        }

        for (int i = 0;i < 1000000; ++i)            

        { 

               pool.free(Array[i]);

        }

}

int _tmain(int argc, _TCHAR* argv[])

{

        UseObjectPool();

        UseNormalPool();

       

        Array = new MyData2*[1000000];

        int TickCount;

 

        puts("Alloc and Free 1000000 count");

        TickCount = GetTickCount();

        Test1NewAndDelete();

        printf("new And delete : %dms\n", GetTickCount() - TickCount);

 

        TickCount = GetTickCount();

        Test1MallocAndFree();

        printf("malloc And Free : %dms\n", GetTickCount() - TickCount);

 

        TickCount = GetTickCount();

        Test1BoostPool();

        printf("boost pool : %dms\n", GetTickCount() - TickCount);

 

        puts("Alloc 1000000 count and Free 1000000 count");

 

        TickCount = GetTickCount();

        Test2NewAndDelete();

        printf("new And delete : %dms\n", GetTickCount() - TickCount);

 

        TickCount = GetTickCount();

        Test2MallocAndFree();

        printf("malloc And Free : %dms\n", GetTickCount() - TickCount);

 

        TickCount = GetTickCount();

        Test2BoostPool();

        printf("boost pool : %dms\n", GetTickCount() - TickCount);

        return 0;

}

 

?

Lyn
조회 수 15485 추천 수 0 댓글 2

"비밀글입니다."


Lyn
조회 수 36732 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
아래코드는 C++ Builder 2009에서 테스트되었습니다.

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

#include <vcl.h>
#include <vector>
#include <memory>
#include <iostream>
#include <cstdlib>
#pragma hdrstop

#include <tchar.h>

using namespace std;
using namespace std::tr1;

class Test
{
public:
    int i;
    Test()
    {
        cout << "Test is Create!" << endl;
    }
    Test(const Test& )
    {
        cout << "Test's Copy Constructor!" << endl;
    }
    ~Test()
    {
        cout << "Test is Destroy!" << endl;
    }
};
using namespace std;

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

#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
    cout << "스택에 1개 생성" <<endl;
    Test t1; // 생성 되고, 함수가 끝날때 파괴 될 것

    cout << "힙에 1개 생성" <<endl;
    Test* t2 = new Test; //생성
    cout << "힙에서 1개 파괴" <<endl;
    delete t2; //파괴

    cout << "스택에 10개 생성" <<endl;
    Test t3[10];
    vector<Test> v1;

    cout << "복사생성자가 작동한다" <<endl;
    for(int i=0;i<10;++i)
    {
        v1.push_back(t3[i]);
        //이렇게 하면 Copy Contructor 가 작동하므로 오버헤드가 큼
        //게다가 반드시 동적으로 할당해야 하는 VCL 객체에는 사용이 불가능
    }

    cout << "힙에 10개 생성 후 Vector에 넣는다" << endl;
    vector<Test*> v2;
    for(int i=0;i<10;++i)
    {
        Test* tt = new Test;
        v2.push_back(tt);
        //이렇게 하면 동적으로 할당할 수 있음.
        //그러나 vector 를 파괴하기 전에 일일히 루프를 돌면서 delete 해줘야함
        //vetror가 파괴될때 내장하고 있는 모든 객체를 파괴할 수는 없을까?
        //VCL 에서는 TObjectList 클래스를 제공한다! 그러나 이는 C++ 표준이 아니다.
        //게다가 Templete Class 가 아니라 Casting 을 추가로 해줘야 한다는 부담도있다
    }
    cout << "Vector 에 있는 10개를 파괴" << endl;
    for(int i = 10 - 1;i >= 0;--i)
    {
        delete v2[i];
    }

    cout << "shared_ptr 을 이용하여 넣는다" << endl;
    vector<shared_ptr<Test> > v3;
    for(int i=0;i<10;++i)
    {
        shared_ptr<Test> spt(new Test);
        v3.push_back(spt);
    //vector 인 v3 역시 Main이 끝나야 파괴됨.
    //v3이  파괴되기 전 shared_ptr 의 효과에 의해 v3 이 가지고있던 Test가 모두 파괴
    }

    cout << "벡터 자체를 동적으로 생성해서 테스트 해 보자" << endl;
    vector<shared_ptr<Test> > *v4 = new vector<shared_ptr<Test> >;
    for(int i=0;i<10;++i)
    {
        shared_ptr<Test> spt(new Test);
        v4->push_back(spt);
    }
    cout << "벡터를 박살내면 가지고 있던 Test 10개도 다 박살난다" << endl;
    delete v4;

    system("pause"); //이게 끝나야 Main 이 끝나므로 t1은 이 뒤에 파괴
    //vector 인 v3 역시 Main이 끝나야 파괴됨.
    //v3이  파괴되기 전 shared_ptr 의 효과에 의해 v3 이 가지고있던 Test가 모두 파괴
}
//---------------------------------------------------------------------------

/*
Ps. CopyConstructor 가 10번이 아닌 그 이상 실행 되는데.. 그 이유는 Vector 가 공간이 부족해서 재할당을 하면서 다시 복사생성자가 호출되기 때문입니다. 생각보다 오버헤드가 많이큽니다.
*/
?

Lyn
조회 수 35621 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
STL 에서는 B-Tree 기반의 Collection 이 준비되어 있는데, set ,multiset ,map ,multimap 의 4 종류이다.

그에 반헤 TR1에서는 위의 4종류의 Collection 에 대응되는 Hash 기반의 Collection 을 제공한다.
이름하여 unordered 시리즈(unordered_set, unordered_multiset, unordered_map, unordered_multimap) 이다. (이름너무 길다)

기본적인 사용법은 STL 의 콜렉션과 완전히 같으니 그냥 무시하도록 하겠다.

제일 기본적인 unordered_set 에 대해서만 예제를 보자

#include <iostream>
#include <string>
#include <unordered_set>

using namespace std;
using namespace std::tr1;

int main()
{
    unordered_set<string> UnOrderSet;

    UnOrderSet.rehash(10); //버켓의 갯수를 정의한다.
    //UnOrderSet.insert("김호광");
    UnOrderSet.insert("남병철");
    UnOrderSet.insert("류종택");
    UnOrderSet.insert("린");
    UnOrderSet.insert("박지훈");

    if(UnOrderSet.find("김호광") != UnOrderSet.end())
    {
        cout << "김호광 님은 볼랜드 포럼 회원입니다." << endl;
    }
    else
    {
        cout << "김호광 님은 볼랜드 포럼 회원이 아닙니다." << endl;
    }
}

위에말한대로 기본적인 사용법은 set 과 완전히 동일하다.
중요한 것은 rehash 매소드.  버켓의 갯수가 너무 많으면 메모리 낭비가 극심해지고, 너무 작으면 성능이 나빠집니다. 이래저래 귀찮은 Collection 이라 할 수 있겠군요





기본적으로 unordered_set 은 4개의 템플릿 인수를 받아드립니다.

Value(사용할 Type),  Hash(Value 를 Hash화 하는 함수객체), Pred(비교함수객체), Alloc(할당자)의 순서인데
Hash, Pred, Alloc 은 디폴트 파라미터가 있으므로 사용 하지 않아도 무방하다.

만약 기본적으로 C++에서 제공하는 놈(int, string, double 등등...) 들이 아닌 다른놈들을 사용하려면?
2가지 구현이 필요하다.

첫째로 == 연산자의 오버로딩, 두번째로 해시함수객체의 제공이다.  unordered_set의 2번째 파라메터인 Hash를 내가 사용하기 원하는 타잎을 Hash 할 수 있도록 제공 해 주는것이 필수적이다.

#include <iostream>
#include <string>
#include <unordered_set>

using namespace std;
using namespace std::tr1;

struct TTest
{
    int i;
    double d;

    bool operator == (const TTest &T) const
    {
      return ((i == T.i) && (d == T.d));
    }


};

struct TTestHash
{
    size_t operator () (const TTest &T) const
    {
        return T.i;  //그냥 간단하게 i값을 해시값 취급 해버렷다
    }
};

int main()
{
    TTest test[2];


    unordered_set<TTest, TTestHash> UnOrderSet;

    test[0].i = 5;
    test[0].d = 3.14;

    test[1].i = 9;
    test[1].d = 180.36;

    UnOrderSet.insert(test[0]);
    UnOrderSet.insert(test[1]);

    TTest FindValue;
    FindValue.i = 5;
    FindValue.d = 3.15;

    if(UnOrderSet.find(FindValue) != UnOrderSet.end())
    {
        cout << "찾는 객체가 있습니다" << endl;
    }
    else
    {
        cout << "찾는 객체가 없습니다" << endl;
    }
}

위처럼 사용자 정의타잎 TTest 를 정의하고, 그에대한 해시함수객체 TTestHash 를 정의한 후, unordered_set 을 생성할 시에, Hash함수 객체 타잎을 제공하엿다.



결론을 내자면...

1. 기본타잎을 쓰더라도 어느정도 데이터의 양을 예측 해야 만족스러운 성능이 나온다.
2. 사용자 정의타잎을 쓰고 싶으면 Hash 를 재정의 해야 하기때문에 얼마나 Hash 를 잘 시키느냐에 따라 성능이 크게 달라진다.
3. 위의 조건을 다 만족시킨다면 상황에따라 다르겠지만 대충 set 의 2배정도의 성능을 보여주는 것 같다(속도측면, 메모리는 아무래도 소비가 크다)
4. C++ Collection 너무 많다 =_=;;; 상황에 따라 최적의 Collection 을 찾는 것 만도 일이다.
5. STL 의 Collection 들은 별 존재가치가 없어졋단 생각도 든다... 메모리 아껴야되는 상황이 아니라면(오해의 소지 매우 많음!)

Ps. C++ 에서는 보통 Containers 라 하는 것 같은데... 익숙하지 않아 그냥 일반적인 Collection 이란 용어를 사용했다.
?

Board Pagination Prev 1 ... 2 3 4 5 6 7 ... 8 Next
/ 8