C++ std::move

2021. 3. 24. 10:45·SW개발/C++
반응형

std::move

  • <utility> 라이브러리

  • 인자로 들어온 값을 R-value로 리턴해준다.


예제

  • std::move를 사용하지 않은 예제

    main.cpp

    #include <iostream>
    #include "Resource.h"
    #include "AutoPtr.h"
    using namespace std;
    
    int            main()
    {
      AutoPtr<Resource> res1(new Resource(10000000));
    
      cout << res1.ptr_ << endl;
    
      AutoPtr<Resource> res2 = res1;
    
      cout << res1.ptr_ << endl;
      cout << res2.ptr_ << endl;
    }
    
    /* stdout stderr
    Resource length constructed
    AutoPtr default constructor
    0158E360
    AutoPtr copy constructor
    Resource default constructed
    Resource copy assignment
    0158E360
    0158E408
    AutoPtr destructor
    Resource destoryed
    AutoPtr destructor
    Resource destoryed
    */

    Resource.h

    #pragma once
    
    #include <iostream>
    
    class Resource
    {
    public:
      int    *data_ = nullptr;
      unsigned length_ = 0;
    
      Resource()
      {
        std::cout << "Resource default constructed\n";
      }
    
      Resource(unsigned length)
      {
        std::cout << "Resource length constructed\n";
        init(length);
      }
    
      Resource(const Resource& res)
      {
        std::cout << "Resource copy constructed\n";
        init(res.length_);
        for (unsigned i = 0; i < length_; ++i)
          data_[i] = res.data_[i];
      }
    
      ~Resource()
      {
        std::cout << "Resource destoryed\n";
    
        if (data_ != nullptr) delete[] data_;
      }
    
      void    init(unsigned length)
      {
        data_ = new int[length];
        length_ = length;
      }
    
      Resource& operator = (Resource& res)
      {
        std::cout << "Resource copy assignment\n";
        if (&res == this) return *this;
    
        if (data_ != nullptr) delete[] data_;
        init(res.length_);
        for (unsigned i = 0; i < length_; ++i)
          data_[i] = res.data_[i];
        return *this;
      }
    
      void print()
      {
        for (unsigned i = 0; i < length_; ++i)
          std::cout << data_[i] << ' ';
        std::cout << std::endl;
      }
    };

    AutoPtr.h

    #pragma once
    
    #include <iostream>
    
    template<class T>
    class AutoPtr
    {
    public:
      T* ptr_;
    
      AutoPtr(T *ptr = nullptr)
        : ptr_(ptr)
      {
        std::cout << "AutoPtr default constructor\n";
      }
    
      AutoPtr(const AutoPtr& a)
        : ptr_(a.ptr_)
      {
        std::cout << "AutoPtr copy constructor\n";
        ptr_ = new T;
        *ptr_ = *a.ptr_;
      }
    
      AutoPtr(AutoPtr&& a)
        : ptr_(a.ptr_)
      {
        std::cout << "AutoPtr move constructor\n";
        a.ptr_ = nullptr;
      }
    
      ~AutoPtr()
      {
        std::cout << "AutoPtr destructor\n";
        if (ptr_ != nullptr) delete ptr_;
      }
    
      AutoPtr& operator = (const AutoPtr& a)
      {
        std::cout << "AutoPtr copy assignment\n";
        if (&a == this)
          return *this;
    
        if (ptr_ != nullptr) delete ptr_;
    
        ptr_ = new T;
        *ptr_ = *a.ptr_;
        return *this; 
      }
    
      AutoPtr& operator = (AutoPtr&& a)
      {
        std::cout << "AutoPtr move assignment\n";
    
        if (&a == this)
          return *this;
    
        if (ptr_ != nullptr) delete ptr_;
    
        ptr_ = a.ptr_;
        a.ptr_ = nullptr;
    
        return *this;
      }
    };

  • 위의 코드에서 main.cpp에 <utility> 라이브러리를 include 하고, std::move를 사용하면 다음과 같다.

    main.cpp

    #include <iostream>
    #include <utility>
    #include "Resource.h"
    #include "AutoPtr.h"
    using namespace std;
    
    int            main()
    {
      AutoPtr<Resource> res1(new Resource(10000000));
    
      cout << res1.ptr_ << endl;
    
      AutoPtr<Resource> res2 = std::move(res1);
    
      cout << res1.ptr_ << endl;
      cout << res2.ptr_ << endl;
    }
    
    /* stdout stderr
    Resource length constructed
    AutoPtr default constructor
    00CADF50
    AutoPtr move constructor
    00000000
    00CADF50
    AutoPtr destructor
    Resource destoryed
    AutoPtr destructor
    */

Swap 예제

main.cpp

  #include <iostream>
  #include <utility>
  #include "Resource.h"
  #include "AutoPtr.h"
  using namespace std;

  template<typename T>
  void        MySwap(T& a, T& b)
  {
    T tmp{ std::move(a) };
    a = std::move(b);
    b = std::move(tmp);
  }

  int            main()
  {
    AutoPtr<Resource> res1(new Resource(3));
    res1->setAll(3);

    AutoPtr<Resource> res2(new Resource(5));
    res2->setAll(5);

    res1->print();
    res2->print();

    MySwap(res1, res2);

    res1->print();
    res2->print();
  }

  /* stdout stderr
  Resource length constructed
  AutoPtr default constructor
  Resource length constructed
  AutoPtr default constructor
  3 3 3
  5 5 5 5 5
  AutoPtr move constructor
  AutoPtr move assignment
  AutoPtr move assignment
  AutoPtr destructor
  5 5 5 5 5
  3 3 3
  AutoPtr destructor
  Resource destoryed
  AutoPtr destructor
  Resource destoryed
  */

Resource.h

  #pragma once

  #include <iostream>

  class Resource
  {
  public:
    int    *data_ = nullptr;
    unsigned length_ = 0;

    Resource()
    {
      std::cout << "Resource default constructed\n";
    }

    Resource(unsigned length)
    {
      std::cout << "Resource length constructed\n";
      init(length);
    }

    Resource(const Resource& res)
    {
      std::cout << "Resource copy constructed\n";
      init(res.length_);
      for (unsigned i = 0; i < length_; ++i)
        data_[i] = res.data_[i];
    }

    ~Resource()
    {
      std::cout << "Resource destoryed\n";

      if (data_ != nullptr) delete[] data_;
    }

    void    init(unsigned length)
    {
      data_ = new int[length];
      length_ = length;
    }

    Resource& operator = (Resource& res)
    {
      std::cout << "Resource copy assignment\n";
      if (&res == this) return *this;

      if (data_ != nullptr) delete[] data_;
      init(res.length_);
      for (unsigned i = 0; i < length_; ++i)
        data_[i] = res.data_[i];
      return *this;
    }

    void    print()
    {
      for (unsigned i = 0; i < length_; ++i)
        std::cout << data_[i] << ' ';
      std::cout << std::endl;
    }

    void    setAll(const int& v)
    {
      for (unsigned i = 0; i < length_; ++i)
        data_[i] = v;
    }
  };

AutoPtr.h

  #pragma once

  #include <iostream>

  template<class T>
  class AutoPtr
  {
  public:
    T* ptr_;

    AutoPtr(T *ptr = nullptr)
      : ptr_(ptr)
    {
      std::cout << "AutoPtr default constructor\n";
    }

    AutoPtr(const AutoPtr& a)
      : ptr_(a.ptr_)
    {
      std::cout << "AutoPtr copy constructor\n";
      ptr_ = new T;
      *ptr_ = *a.ptr_;
    }

    AutoPtr(AutoPtr&& a)
      : ptr_(a.ptr_)
    {
      std::cout << "AutoPtr move constructor\n";
      a.ptr_ = nullptr;
    }

    ~AutoPtr()
    {
      std::cout << "AutoPtr destructor\n";
      if (ptr_ != nullptr) delete ptr_;
    }

    AutoPtr& operator = (const AutoPtr& a)
    {
      std::cout << "AutoPtr copy assignment\n";
      if (&a == this)
        return *this;

      if (ptr_ != nullptr) delete ptr_;

      ptr_ = new T;
      *ptr_ = *a.ptr_;
      return *this; 
    }

    AutoPtr& operator = (AutoPtr&& a)
    {
      std::cout << "AutoPtr move assignment\n";

      if (&a == this)
        return *this;

      if (ptr_ != nullptr) delete ptr_;

      ptr_ = a.ptr_;
      a.ptr_ = nullptr;

      return *this;
    }

      T* operator->() const { return ptr_; }
  };

대부분의 라이브러리는 R-value에 대해서도 정의가 되어있다.

  #include <iostream>
  #include <utility>
  #include <vector>
  using namespace std;

  int            main()
  {
    vector<string> v;
    string str = "Hello";

    v.push_back(str);

    cout << str << endl;
    cout << v[0] << endl;

    v.push_back(std::move(str));

    cout << str << endl;
    cout << v[0] << ' ' << v[1] << endl;
  }

  /* stdout stderr
  Hello
  Hello

  Hello Hello
  */
반응형
저작자표시 (새창열림)

'SW개발 > C++' 카테고리의 다른 글

C++ shared_ptr  (0) 2021.03.24
C++ unique_ptr  (0) 2021.03.24
C++ 이동 생성자와 이동 대입 (Move Constructor and Move Assignment)  (0) 2021.03.24
C++ 출력 스트림 끊기  (0) 2021.03.24
C++ R-value Reference  (0) 2021.03.24
'SW개발/C++' 카테고리의 다른 글
  • C++ shared_ptr
  • C++ unique_ptr
  • C++ 이동 생성자와 이동 대입 (Move Constructor and Move Assignment)
  • C++ 출력 스트림 끊기
Caniro
Caniro
  • Caniro
    Minimalism
    Caniro
  • 전체
    오늘
    어제
    • 전체보기 (319)
      • SW개발 (268)
        • Java Spring (6)
        • C++ (186)
        • Python (21)
        • Linux (16)
        • 알고리즘 (13)
        • Git (4)
        • Embedded (1)
        • Raspberrypi (9)
        • React (3)
        • Web (2)
        • Windows Device Driver (6)
      • IT(개발아님) (46)
        • Windows (26)
        • MacOS (7)
        • Utility (11)
      • 챗봇 짬통 (0)
      • 일상 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    mspaint
    백기선
    알림
    citrix workspace
    맥북 카카오톡 알림 안뜸
    SFC
    그림판
    제외
    java
    스프링 프레임워크 핵심 기술
    Workspace
    SunOS 5.1
    시스템 복구
    EXCLUDE
    vscode
    Windows 11
    spring
    dism
    윈도우 명령어
    unix
    KakaoTalk
    Solaris 10
    windows
    MacOS
    스프링
    윈도우
    logi options
    로지텍 마우스 제스처
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Caniro
C++ std::move
상단으로

티스토리툴바