본문 바로가기
언어 정리/C++_개념_lib

std::move()

by 알 수 없는 사용자 2024. 1. 22.

 

 

 

string b = std::move(a); 

a에 Lval가 오는 경우와 Rval 가 오는 경우

-- 

std::move 함수는 인자로 받은 객체를 rvalue reference로 캐스팅하는 유틸리티 함수입니다. 이 함수는 객체의 데이터를 실제로 이동시키지 않으며, 단지 해당 객체를 이동할 수 있는 상태로 만듭니다. 그렇게 함으로써 이동 생성자(move constructor)나 이동 할당 연산자(move assignment operator)가 호출될 수 있게 합니다. 이러한 이동 연산자들은 객체의 내부 리소스(예: 동적 할당된 메모리)의 소유권을 효율적으로 새 객체로 이전하는 데 사용됩니다.

std::move가 호출될 때 인자로 Lvalue가 오는 경우와 Rvalue가 오는 경우에 대해 설명하겠습니다:

  1. Lvalue가 std::move에 전달된 경우: Lvalue는 이름이 있는 객체를 참조합니다 (예: 변수 a). std::move(a)는 a를 rvalue reference로 캐스팅합니다. 이는 a가 이동 가능한 상태임을 나타내며, 이후에 a를 대상으로 이동 생성자나 이동 할당 연산자가 호출될 수 있습니다. 이동 연산이 수행되면 a의 내부 리소스는 새로운 객체 b로 이전되고, a는 빈 상태나 정의되지 않은 상태가 됩니다.
  2. Rvalue가 std::move에 전달된 경우: Rvalue는 이름이 없는 임시 객체를 참조합니다 (예: 함수에서 반환되는 임시 객체). Rvalue는 이미 이동 가능한 상태이므로 std::move를 사용할 필요가 없습니다. 그러나 std::move를 사용하여 Rvalue를 명시적으로 rvalue reference로 캐스팅하는 것은 문제가 되지 않으며, 이 경우에도 이동 생성자나 이동 할당 연산자가 호출될 수 있습니다.

두 경우 모두, std::move는 객체를 이동할 준비가 되었다는 신호를 보내는 역할을 하며, 실제 이동 작업은 이동 생성자나 이동 할당 연산자에 의해 수행됩니다. 이때 중요한 점은 std::move를 호출한 후에는 원본 객체를 더 이상 사용하지 않거나, 값을 재할당하거나 파괴하기 전까지는 접근하지 않는 것이 좋다는 것입니다. 이는 원본 객체가 더 이상 유효한 상태가 아닐 수 있기 때문입니다.


std::move() 

ex)

string b = std::move(a);

a 라는 Lval 를 Rval로 변환시켜
a의 값에 대한 소유권을 b 에게 넘긴다.

#include <iostream>
using namespace std;

void rf_argu(string& s)
{
  string b = std::move(s);
};

void noraml_argu(string s)
{
  string b = std::move(s);
};

class Foo
{
  private:
    string nName;
  public:
    void SetName(string name)
    {
      nName = std::move(name);
    }
};

int main()
{
  cout << "---------------------" << endl;
  int a = 1;
  cout << a << endl;        // 출력값 : 1
  int c = std::move(a);     // 내장 타입(primitive type)의 경우, 이동 시맨틱이 적용 되지 않음
  cout << a << endl;        // 출력값 : 1
  cout << c << endl;        // 출력값 : 1

  string q = "qqq";
  cout<<q<<endl;            // 출력값 : qqq
  string w = std::move(q);  // 클래스 타입(class type)의 경우, 이동 생성자(move constructor)나 이동 대입 연산자(move assignment operator)가 정의되어 있어 이동 시맨틱이 적용됨
  // move() 키워드로 Lval를 Rval로 바꾸면서 resource ownership 을 다른 obj에 넘긴다.
  cout<<q<<endl;            // 출력값 : 
  cout<<w<<endl;            // 출력값 : qqq

  cout << "---------------------" << endl;
  string t_1 = "aaaaaaaaa";
  cout << t_1 <<endl;       // 출력값 : aaaaaaaaa
  rf_argu(t_1);   //  참조에 의한 전달은 t_1 자체를 넘기므로 소유권이 이전되 출력값이 없음
  cout << t_1 <<endl;       // 출력값 : 

  cout << "---------------------" << endl;
  string t_2 = "aaaaaaaaa";
  cout << t_2 <<endl;       // 출력값 : aaaaaaaaa
  noraml_argu(t_2); // 값에 의한 전달은 복사본을 넘기기 때문에 t_2 의 소유권이 이전되지 않음
  cout << t_2 <<endl;       // 출력값 : aaaaaaaaa

  cout << "---------------------" << endl;
  Foo foo;
  string s = "foo";
  foo.SetName(s);           // Lval 를 넘긴 경우 1 copy
  foo.SetName("bar");       // Rval 를 넘긴 경우 0 copy
  cout << s << endl;

}

'언어 정리 > C++_개념_lib' 카테고리의 다른 글

디폴트 파라미터, 함수포인터  (0) 2024.01.22
인수 전달  (0) 2024.01.16
vector  (0) 2024.01.16
for-each  (0) 2024.01.16
enum, 구조체  (0) 2024.01.16

댓글