ShovelingLife
A Game Programmer
ShovelingLife
전체 방문자
오늘
어제
  • 분류 전체보기 (1074) N
    • 그래픽스 (57)
      • 공통 (19)
      • 수학 물리 (22)
      • OpenGL & Vulkan (1)
      • DirectX (14)
    • 게임엔진 (183)
      • Unreal (69)
      • Unity (103)
      • Cocos2D-X (3)
      • 개인 플젝 (8)
    • 코딩테스트 (221)
      • 공통 (7)
      • 프로그래머스 (22)
      • 백준 (162)
      • LeetCode (19)
      • HackerRank (2)
      • 코딩테스트 알고리즘 (8)
    • CS (235)
      • 공통 (21)
      • 네트워크 (44)
      • OS & 하드웨어 (55)
      • 자료구조 & 알고리즘 (98)
      • 디자인패턴 (6)
      • UML (4)
      • 데이터베이스 (7)
    • 프로그래밍 언어 (349) N
      • C++ (168) N
      • C# (90)
      • Java (9)
      • Python (33)
      • SQL (30)
      • JavaScript (8)
      • React (7)
    • 그 외 (10)
      • Math (5)
      • 일상 (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Source Code 좌측 상단에 복사 버튼 추가 완료
  • 언리얼 엔진 C++ 빌드시간 단축 꿀팁
  • 게임 업계 코딩테스트 관련
  • 1인칭 시점으로 써내려가는 글들

인기 글

태그

  • c#
  • 클래스
  • 유니티
  • 백준
  • 파이썬
  • string
  • 문자열
  • SQL
  • Unity
  • 티스토리챌린지
  • 언리얼
  • 포인터
  • 함수
  • 배열
  • 알고리즘
  • 오블완
  • C++
  • 그래픽스
  • C
  • 프로그래머스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ShovelingLife

A Game Programmer

프로그래밍 언어/C++

C++ Copy and Swap idiom

2022. 8. 8. 20:12

C++에선 클래스가 리소스를 관리하고 클래스의 생성/소멸에 맞춰 리소스를 할당/해제한다. 관련된 멤버 함수와 그 역할은 아래와 같다.

  • 생성자: 리소스를 할당한다.
  • 복사 생성자: 리소스를 복사해온다.
  • 복사 대입 연산자: 기존 리소스를 해제하고 리소스를 복사해온다.
  • (C++11부터) 이동 생성자: 리소스를 가져온다.
  • (C++11부터) 이동 대입 연산자: 기존 리소스를 해제하고 리소스를 가져온다.
  • 소멸자: 리소스를 해제한다.

Copy-and-swap idiom은 간결하면서도 강력한 예외 안정성(strong exception safety)을 보장해주는 복사 대입 연산자를 짤 수 있게 해준다. 또한 이동 대입 연산자에를 짤 때에도 유용하다.

 

문자열 리소스를 관리하는 간단한 클래스를 생각해보자.

class Foo
{
    char* data = nullptr;

public:

    Foo() : data(new char[14])
    {
        std::strcpy(data, "Hello, World!");
    }

    Foo(const Foo& other) : data(new char[std::strlen(other.data) + 1])
    {
        std::strcpy(data, other.data);
    }

    ~Foo()
    {
        delete[] data;
    }
};

아래는 잘못된 코드이다.

Foo& operator=(const Foo& other)
{
    if (this != &other)
    {
        char* newData = new char[std::strlen(other.data) + 1];
        std::strcpy(data, other.data);
        delete[] data;
        data = newData;
    }
    return *this; ​
}

std::swap을 이용하도록 하자.

Foo& operator=(Foo other) // note: argument passed by value
{
    std::swap(data, other.data);
    return *this;
}

중복되는 교환 부분을 따로 정의하면서, ADL을 이용해 std::swap을 확장하였다(std::swap을 구체화하는 것은 표준 라이브러리에 간섭하는 것이므로 좋지 않다.

friend void swap(Foo& fst, Foo& snd)
{
    // enable ADL
    using std::swap;
    swap(fst.data, snd.data);
}

Foo(Foo&& other) : data(nullptr)
{
    swap(*this, other);
}

이동 대입 연산자도 결국엔 대입이라 복사 대입 연산자와 크게 다르지 않다. 다른 점은 other​를 복사하지 않는다는 점(리소스 할당이 없으므로 보통 예외가 발생하지 않는다)과 other​가 곧 소멸될 것이라는 점이다. 

class Foo
{
    char* data;

public:
    Foo() : data(new char[14])
    {
        std::strcpy(data, "Hello, World!");
    }

    Foo(const Foo& other) : data(new char[std::strlen(other.data) + 1])
    {
        std::strcpy(data, other.data);
    }

    Foo& operator=(Foo other) // note: argument passed by value
    {
        swap(*this, other);
        return *this;
    }

    Foo(Foo&& other) : data(nullptr)
    {
        swap(*this, other);
    }

    Foo& operator=(Foo&& other)
    {
        swap(*this, other);
        return *this;
    }

    ~Foo()
    {
        delete[] data;
    }

private:

    friend void swap(Foo& fst, Foo& snd)
    {
        // enable ADL
        using std::swap;
        swap(fst.data, snd.data);
    }

    friend std::ostream& operator<<(std::ostream& os, const Foo& foo)
    {
        os << foo.data;
        return os;
    }
};

int main()
{
    const Foo foo;
    std::cout << foo << '\n';
    return 0;
}

출처 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=stkov&logNo=220121638743

저작자표시 (새창열림)

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ 비동기 (Asynchronous) 실행  (0) 2022.08.17
C++ 동기(synchronous)와 비동기(asynchronous) / 블로킹(blocking)과 논블로킹(non-blocking)  (0) 2022.08.16
C++ 위임 생성자 (delegating constructor)  (0) 2022.08.05
C++ NULL과 nullptr의 차이  (0) 2022.08.04
C++ 가변 길이 배열 (Variable Length Array)  (0) 2022.08.02
    '프로그래밍 언어/C++' 카테고리의 다른 글
    • C++ 비동기 (Asynchronous) 실행
    • C++ 동기(synchronous)와 비동기(asynchronous) / 블로킹(blocking)과 논블로킹(non-blocking)
    • C++ 위임 생성자 (delegating constructor)
    • C++ NULL과 nullptr의 차이
    ShovelingLife
    ShovelingLife
    Main skill stack => Unity C# / Unreal C++ Studying Front / BackEnd, Java Python

    티스토리툴바