Search

'nullptr'에 해당되는 글 2건

  1. 2010.06.25 [Step. 04] nullptr, interior_ptr, pin_ptr 2
  2. 2010.01.28 nullptr 2

[Step. 04] nullptr, interior_ptr, pin_ptr

C++/CLI 2010. 6. 25. 08:30 Posted by 알 수 없는 사용자

nullptr

 

C/C++에서 포인터를 초기화 할 때 ‘NULL’을 사용합니다. 그러나 VC++ 10에는 C++0x에서는 포인터를 초기화 할 때 NULL 대신 새로 생긴 ‘nullptr’을 사용할 수 있게 되었습니다.


C++/CLI는 이전부터 nullptr이 있었습니다.

C++/CLI에서는 ref 클래스의 핸들을 초기화 할 때는 nullptr을 사용합니다.

C++/CLI, C++0x nullptr C/C++ 처럼 ‘0’이 아니라는 것을 잘 기억하시기 바랍니다.

 

 

 

interior_ptr

 

interior_ptr은 관리 힙(managed heap. GC겠죠) 상의 value type나 기본형을 가리키는 포인터라고 할 수 있습니다. interior_ptrvalue type나 기본형을 비관리 코드의 포인터처럼 사용하고 싶을 때 사용하면 좋습니다.

 

< 코드 1. >

ref class REFClass

{

public:

    int nValue;

};

 

void SetValue( int* nValue )

{

    *nValue = 100;

}

 

 

int main()

{

    REFClass^ refClass = gcnew REFClass;

    SetValue( &refClass->nValue );  // 에러

}

 

위 코드를 빌드 해 보면 SetValue( &refClass->nValue ); 에서 빌드 에러가 발생합니다. 매니지드 힙에 있는 것은 그 위치가 변하므로 비 관리 코드의 포인터를 넘길 수가 없습니다. 그럼 <코드 1>를 정상적으로 빌드 하기 위해서 interior_ptr를 사용해 보겠습니다.

 

< 코드 2. >

ref class REFClass

{

public:

    int nValue;

};

 

void SetValue( interior_ptr<int> nValue )

{

    *nValue = 100;

}

 

 

int main()

{

    REFClass^ refClass = gcnew REFClass;

    SetValue( &refClass->nValue );

}

 


<코드 2> SetValue의 파라미터로 비관리 코드의 참조나 포인터를 넘길 수도 있습니다.

< 코드 3. >

#include <iostream>

 

 

void SetValue( interior_ptr<int> nValue )

{

    *nValue = 100;

}

 

int main()

{

           int nValue = 50;

           SetValue( &nValue );

 

           std::cout << nValue << std::endl;

 

           getchar();

           return 0;

}

 

그리고 interior_ptr에 대신 C++/CLI의 참조(‘%’)를 사용하는 방법도 있습니다.

 

 

 

 

pin_ptr

 

pin_ptr은 관리 힙 상의 value type나 기본형을 비관리 코드에서 포인터로 사용하고 싶을 때 사용하는 기능입니다. 가장 필요한 경우가 C++/CLI에서 기존의 비관리 코드로 만들어 놓은 라이브러리를 사용할 때입니다.

 

< 코드 4. >

ref class REFClass

{

public:

    int nValue;

};

 

void SetValue( int* pValue )

{

    *pValue = 100;

}

 

 

int main()

{

    REFClass^ refClass = gcnew REFClass;

pin_ptr<int> pValue = &refClass->nValue;

    SetValue( pValue );

pValue = nullptr;

}

 

pin_ptr에 메모리 주소를 할당하는 것을 ‘pin’이라고 부르고 사용이 끝난 후 nullptr로 초기화 하는 것을 ‘unpin’ 이라고 부릅니다. pin_ptr 사용이 끝난 후 가능한 빨리 unpin 해주는 것이 좋습니다.

 

 

 

 

interior_ptr pin_ptr의 차이점

 

interipor_ptr pin_ptr은 둘 다 관리 힙 상의 value type이나 기본형을 가리키는 포인터로 사용되지만 interior_ptr은 관리 힙 상에서 인스턴스가 이동하여도 올바르게 추적할 수 있는 포인터로 런타임의 지배하에 있습니다(즉 인스턴스가 관리 힙 상에서 이동하여도 괜찮습니다).


pin_ptr은 관리 힙 상의 value type을 비관리 코드에서 사용하고 싶을 때 사용합니다. 당연히 이 때는 관리 힙에 있는 인스턴스가 이동하면 안되므로 인스턴스의 이동을 금지합니다.

 

interipor_ptr pin_ptr의 같은 점 : 포인터처럼 사용할 수 있다.

interipor_ptr pin_ptr 다른 점 : interipor_ptr은 관리 코드 상에서 포인터로 사용하고, pin_ptr는 비관리 코드에 포인터로 넘길 때 사용합니다.

 

 

interipor_ptr pin_ptr을 공부했으니 다음에는 C++/CLI에서 비관리 C++과 혼합해서 사용할 때 어떻게 해야 하는지 설명하겠습니다.

 

 

 

 

참고

http://cppcli.shacknet.nu/cli:interior_ptr

http://cppcli.shacknet.nu/cli:pin_ptr

http://cppcli.shacknet.nu/cli:interior_ptr%E3%81%A8pin_ptr%E3%81%AE%E9%81%95%E3%81%84

 

nullptr

C++0x 2010. 1. 28. 09:00 Posted by 알 수 없는 사용자

오랜만에 팀 블로그에 C++0x 관련 글을 올립니다.

이미 알고 계시겠지만 Visual Stuido 2010 Beta2에 새로운 C++0x 기능이 추가 되었습니다.

추가된 것은 nullptr 이라는 키워드 입니다.

nullptr C++0x에서 추가된 키워드로 널 포인터(Null Pointer)를 나타냅니다.

 

 

null_ptr이 필요한 이유

 

C++03까지는 널 포인터를 나타내기 위해서는 NULL 매크로나 상수 0을 사용하였습니다.

그러나 NULL 매크로나 상수 0을 사용하여 함수에 인자로 넘기는 경우 int 타입으로 추론되어 버리는 문제가 발생 합니다.

 

< List 1 >

#include <iostream>

 

using namespace std;

 

void func( int a )

{

cout << "func - int " << endl;

}

 

void func( double *p )

{

cout << "func - double * " << endl;

}

 

int main()

{

func( static_cast<double*>(0) );

                 

func( 0 );

  func( NULL );

                 

getchar();

return 0;

}

 

< 결과 >

 


첫 번째 func 호출에서는 double* 로 캐스팅을 해서 의도하는 func이 호출 되었습니다. 그러나 두 번째와 세 번째 func 호출의 경우 func( doube* p ) 함수에 널 포인터로 파라미터로 넘기려고 했는데 의도하지 않게 컴파일러는 int로 추론하여 func( int a )가 호출 되었습니다.

 

바로 이와 같은 문제를 해결하기 위해서 nullptr 이라는 키워드가 생겼습니다.

 

 

 

nullptr 구현안

 

C++0x에서 nullptr의 드래프트 문서를 보면 nullptr은 아래와 같은 형태로 구현 되어 있습니다.

 

const class {

public:

    template <class T>

    operator T*() const

    {

        return 0;

    }

 

    template <class C, class T>

    operator T C::*() const

    {

        return 0;

    }

 

private:

    void operator&() const;

 

} nullptr = {};

 

 

 

nullptr 사용 방법

 

사용방법은 너무 너무 간단합니다. ^^

그냥 예전에 널 포인터로 0 이나 NULL을 사용하던 것을 그대로 대처하면 됩니다.

 

char* p = nullptr;

 

<List1>에서 널 포인트를 파라미터로 넘겨서 func( double* p )가 호출하게 하기 위해서는

func( nullptr );

로 호출하면 됩니다.

 



nullptr의 올바른 사용과 틀린 사용 예

 

 

올바른 사용

char* ch = nullptr; // ch에 널 포인터 대입.

sizeof( nullptr ); // 사용 할 수 있습니다. 참고로 크기는 4 입니다.

typeid( nullptr ); // 사용할 수 있습니다.

throw nullptr; // 사용할 수 있습니다.

 

 

틀린 사용

int n = nullptr; // int에는 숫자만 대입가능한데 nullptr은 클래스이므로 안됩니다.

 

Int n2 = 0

if( n2 == nullptr ); // 에러

 

if( nullptr ); // 에러

 

if( nullptr == 0 ); // 에러

 

nullptr = 0; // 에러

 

nullptr + 2; // 에러

 

 

 

nullptr 너무 간단하죠? ^^

VC++ 10에서는 예전처럼 널 포인터를 나타내기 위해서 0 이나 NULL 매크로를 사용하지 말고 꼭 nullptr을 사용하여 함수나 템플릿에서 널 포인터 추론이 올바르게 되어 C++을 더 효율적으로 사용하기 바랍니다.^^

 

 

 

짜투리 이야기...... ^^


왜 nullptr 이라고 이름을 지었을까?

nullptr을 만들 때 기존의 라이브러리들과 이름 충돌을 최대한 피하기 위해서 구글로 검색을 해보니 nullptr로 검색 결과가 나오는 것이 별로 없어서 nullptr로 했다고 합니다.

제안자 중 한 명인 Herb Sutter은 현재 Microsoft에서 근무하고 있는데 그래서인지 C++/CLI에서는 이미 nullptr 키워드를 지원하고 있습니다.

 

 

C++0x 이야기

근래에 Boost 라이브러리의 thread 라이브러리가 C++0x에 채택 되었다고 합니다. Boost에 있는 많은 라이브러리가 C++0x에 채택되고 있으므로 컴파일러에서 아직 지원하지 않는 C++0x의 기능을 먼저 사용해 보고 싶다면 꼭 Boost 라이브러리를 사용해 보기 바랍니다.

 


 

참고

http://d.hatena.ne.jp/faith_and_brave/20071002/1191322319

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf

http://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr

http://d.hatena.ne.jp/KZR/20080328/p1