C++0x RValue Reference 라는것이 추가 되었다.


RValue Reference는  Move semantics와 Perfect forwarding 이라는 두가지 기능을 가진다.


1. Move semantics

기존 부터 있던 Reference는 LValue Reference 라고 불린다.

int n = 10;
int &r = n;  // LValue Reference
int *p = &n;  // 포인터 참조 방식
cout << r << " " << *p << endl;

C++의 참조는 내부적으로 포인터를 사용하여 참조를 하게 되지만 사용함에 있어 보다 우아하게(?) 사용을 할 수 있다는 장점이 있다.


반면 RValue Reference는 아래와 같이 사용한다.

int n = 10;
int &&r =n; // 그런데 기존 참조랑 머가 틀리냐??

int, long 등의 기본 타입과 기존 클래스의 복사생성자, 대입연산자에 대해서는 RValue Reference 참조는 기존 Value Reference와 똑같이 동작을 한다.

하지만 RValue Reference는 객체(변수)의 주소를 참조하는 기존의 LValue Reference와 틀리게,
RValue Reference 로 겹지정한 복사생성자 및 대입연산자를 따로 구현, 그리고 그것을 의도적으로 호출하게 할 수 있다.

그리고 그 RValue Reference 로 겹지정한 복사생성자 및 대입연산자에는,
임시객체애 대해서 복사가 아닌  메모리를 이동 (Move) 하는 방법으로 임시 객체의 생성및 소멸에 대한 비용을 줄이는 구현이가능해 진것이다.

소유권 이전 기법을 사용하는 auto_ptr 처럼..



class Item
{
  public:
    Item() : p(new char[100]) {}
    Item(const Item &t) : p(new char[100]) {  memcpy(p, t.p);  } // 복사생성자
    Item(Item &&t) : p(t.p) { t.p = NULL;  } // Move 생성자

    // Item& operator=(const Item &t) { return *this; } // 대입연산자
    // Item& operator=(Item &&t) { return *this; } // Move 대입 연산자
    // ...
   ~Item() { if (p) delete p; }
  
  private:
    char *p;
};

Item&& foo()
{
  Item item;
  // ...
  return item;
}

int main()
{
  Item item;
  Item t = item; // 복사생성자 호출
  Item &r = item; // 참조

  Item &&rr = Item; // 참조
  Item &&mv = std::move(item);  // Move 생성자
  Item &&mvt = foo(); // // Move 생성자
}

위의 코드와 같이 foo() 함수에서 RValue Reference로 리턴을 하게 되면,
Item 객체의 RValue Reference 버전의 Move 생성자가 호출되고
Move 생성자에서 내부 멤버인 포인터의 소유권을 이전하여 임시객체에 대해서 필요 없는 생성-소멸의 과정을 거치지 않게끔 할 수 있는것이다.

그리고 강제로 Move 생성자, Move 대입 연산자를 호출 하기 위해서 std::move() 함수를  이용 할 수도 있다.


C++0x 의 STL에는 RValue Reference 의 코드가 적용 되어 있어 사용하는 것 만으로도 성능 효과를 볼 수가 있다고 한다.
대략 다음과 같은 코드..

std::string s = "s";
std::string str;
str = s + "t" + "r" + "i" + "g";  // 임시객체 (RValue Reference) 사용



2. Perfect forwarding

template 의 내부 함수가 참조 및 상수의 값을 파라미터로 받을 경우 관련되서 여러 개의 버전 구현을 해야하는 문제를,
RValue Reference의 문법으로 하나로 처리 하는 내용.
(자세한 내용은 아래링크 -_-; )



참고 : http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx


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

boost::asio 클라이언트 소켓 (timeout 기능)  (0) 2010.10.14
이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
아래 링크의 글 중 Herb Sutter 의 Lambda 예제 및 설명에 관한 리플..
http://herbsutter.wordpress.com/2008/03/29/trip-report-februarymarch-2008-iso-c-standards-meeting/

[]와 []안에 들어가는 내용에 대해서 명쾌하게 설명을..




Herb Sutter

Re binders: Okay, I give! I’ll use a better example next time.

(no name) asked: "How are local variables captured?" You have to specify whether it’s by copy or by reference. So this example is illegal because it tries to use a local variable:

    int numWidgets = 0;
    for_each( v.begin(), v.end(), []( Widget& w )
    {
        ++numWidgets;  // error, numWidgets is not in scope
    } );

If you want to update numWidgets directly, capture it by reference:

    for_each( v.begin(), v.end(), [&numWidgets]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

Or use the shorthand [&] to take all captured variables implicitly by reference:

    for_each( v.begin(), v.end(), [&]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

What if you want a local copy? You say to pass it by value, but for safety reasons the current proposal says you get a read-only copy that you can’t modify:

    for_each( v.begin(), v.end(), [numWidgets]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Or use the shorthand [=] to take all captured variables implicitly by copy:

    for_each( v.begin(), v.end(), [=]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Similarly, for the question: "What will happen in the following case:"

    int flag = 0;
    mypool.run( [] { flag = 1; } );
    cout << flag << endl;

The answer is that the code is illegal, you have to say whether you capture flag by value or by reference, which can be as simple as replacing [] with [=] or [&]. And if you capture by value, you get a read-only copy so you couldn’t assign to it.


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

이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x, RValue Reference  (0) 2009.05.27
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29

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

C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29
asio C++ library  (0) 2008.08.22

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

Unhandled C++ Exceptions  (0) 2007.06.19
OutputDebugString  (0) 2007.05.23
GRETA  (0) 2007.05.14
A non-type template-parameter  (0) 2007.05.14
Member template specialization  (0) 2007.05.14

+ Recent posts