Visual Studio 2010 공식 팀 블로그 @vsts2010

Posted by 흥배

이전 회에서 이야기 했던 것을 토대로 이번에는 코드로 그것을 보여드리도록 하겠습니다. 이전 글에서 알쏭달쏭 했던 분들은 앞으로 보여줄 코드를 보면 앞의 설명에 대해서 이해할 수 있을 것입니다.

 첫 번째 글이 지루하고 애매했다면 두 번째 글부터 아주 흥미롭고 중요한 이야기가 나옵니다.

 

 

 

Move 생성자와 Move 대입 연산자

 

기존의 class에서는 복사 생성자와 대입 연산자만 정의할 수 있었지만 RValue Reference에 의해 ‘Move 생성자‘Move 대입 연산자라는 것이 생겼습니다.

 

< Code 1. QuestInfo 클래스 >

class QuestInfo

{

public:

    // 복사 생성자

    QuestInfo(const QuestInfo& quest)

        : Name(new char[quest.NameLen]), NameLen(quest.NameLen)

    {

        memcpy(Name, quest.Name, quest.NameLen);

    }

 

           // 대입 연산자

    QuestInfo& operator=(const QuestInfo& quest)

    {

        if (this != &quest)

           {

            if (NameLen < quest.NameLen)

              {

                // 버퍼를 확보한다

              }

 

            NameLen = quest.NameLen;

            memcpy(Name, quest.Name, NameLen);

        }

 

        return *this;

    }

 

    // Move 생성자

    QuestInfo(QuestInfo&& quest)

        : Name(quest.Name), NameLen(quest.NameLen)

    {

        quest.Name = NULL;

        quest.NameLen = 0;

    }

 

// Move 연산자

    QuestInfo& operator=(QuestInfo&& quest)

    {

        if( this != &quest )

           {

                     delete Name;

       

                     Name = quest.Name;

        NameLen = quest.NameLen;

 

                     quest.Name = NULL;

        quest.NameLen = 0;

           }

        return *this;

    }

 

private:

    char*  Name;

    int NameLen;

};

 

C++0x 이전에는 없던 것이 Move 생성자 QuestInfo(QuestInfo&& quest) Move 대입 연산자 QuestInfo& operator=(QuestInfo&& quest)입니다.

 

외견 상으로 기존의 복사 생성자, 대입 연산자와의 차이는 함수 파라메터에서 ‘&’가 아닌 ‘&&’을 사용하는 것입니다.

 

 

 

성능이 좋아진다고 했는데….

 

RValue Reference를 설명할 때 이것 덕분에 프로그램의 성능이 좋아진다고 했습니다.

왜 그럴까요? <Code 1>에서 복사 생성자와 Move 생성자, 대입 연산자와 Move 대입 연산자의 구현을 잘 보세요. 다르지 않나요?

 

RValue Reference Move Semantics에 의해 복사가 아닌 메모리 이동이라는 것을 할 수 있습니다. <Code 1> Move 생성자와 Move 대입 연산자는 넘겨 받은 인자를 복사하지 않고 메모리 상의 이동을 하고 있습니다.

 

< Code 2. 복사 생성자와 Move 생성자 >

// 복사 생성자

QuestInfo(const QuestInfo& quest)

        : Name(new char[quest.NameLen]), NameLen(quest.NameLen)

{

      memcpy(Name, quest.Name, quest.NameLen);

}

 

// Move 생성자

// Move 생성자

    QuestInfo(QuestInfo&& quest)

        : Name(quest.Name), NameLen(quest.NameLen)

{

      quest.Name = NULL;

      quest.NameLen = 0;

}

 

복사 생성자는 new로 메모리 할당을 한 후 메모리 복사를 하지만, Move 생성자는 메모리 이동을 하고 있습니다.

 

크기가 작은 오브젝트에서는 큰 의미가 없지만 크기가 큰 오브젝트에서는 그 차이가 무시할 수 없을 것입니다.

 

 

 

RValue Reference LValue Reference는 언제 사용할까요?

 

RValue Reference LValue Reference(기존의 참조)는 언제 사용하는지 구분 할 수 있으시나요?

RValue Reference가 생김으로 참조에 관한 룰이 좀 더 추가 되었습니다. 또한 이 두 개의 참조에 대해서 정확하게 알기 위해서는 참조에 대해서 좀 더 세세하게 알아야 됩니다.

그래서 어떤 사람들은 RValue Reference가 좋기는 하지만 이것 때문에 가뜩이나 복잡한 C++이 더 복잡하게 되었다고 불평하기도 합니다.

 

글이 좀 길어져서 RValue Reference가 사용되는 경우에 대한 것은 다음 글에서 코드로 보여드리겠습니다.

 

 

ps :

RValue Reference에 대해서 상세하게 알고 싶은 분들은 Microsoft VC++ 팀 블로그에 포스팅 된 글을 보시기를 바랍니다(영어이고, 내용도 길고, 좀 복잡해서 한번에 팍 하고 이해는 안될 수 있습니다).

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

혹시 위 글을 꼭 알고 싶은데 영어 때문에 난감하고, 시간이 부족하니 정리해 주기를 바라는 분이 있다면 댓글로 알려주시면 뒤에 제가 이 글을 정리해서 올려보겠습니다.

 

저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요

  1. 정의의소 2009/05/06 18:15

    재밌게 잘 봤습니다. 코딩 안 한지가 오래되어서 가물가물 거리네요.. ㅡㅡ;

    • 부족한 글인데 좋게 봐주셨어 고맙습니다.^^
      코딩은 손 놓으면 감 잠는데 시간이 살짝 걸리죠