ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++ Primer CH13. Copy Control
    c++ 2024. 1. 21. 16:35

    keywords: copy constructor, move constructor, copy-assignment operator, move-assignment operator, destructore

     

    copy control

    명시적으로 정의해놓지 않으면 컴파일러가 알아서 만들어서 사용함 → 오작동 가능성

    13.1.1 The Copy Constructor

    규칙1: copy constructor의 첫번째 인자는 무조건 참조자이다.

    • 보통 const 붙인다.

    The synthesized Copy Constructor

    컴파일러가 자동생성해주는 것을 의미

    default constructor과는 달리, 우리가 다른 copy constructor 명시적 정의해줘도 컴파일러가 생성해줌

    copy constructor의 각각의 요소는 각자의 복사 규칙에 따라 복사가 이루어진다.

    1. built-in → 그냥 복사
    2. class → 해당 클래스의 copy constructor에 의해
    3. 배열,벡터 등 sequence containers → 각각의 요소의 copy constructor에 의해

    초기화(initialization) → 처음에 정의 내릴 때 대입하는 것

    할당 → 정의 내린 이후에 = 기호로 값을 교체해주는 것.

    string s = "str" // 초기화
    s = "aaa" // 할당
    

     

    13.1.3 The destructor

    static변수를 제외한 해당 객체의 모든 관련된 리소스를 파괴하는 함수

    class Foo {
    public:
    	~Foo(); // destructor
    }
    

    destructor는 파라미터를 받지 않기 때문에 overload할 수 없다.

    • overload: 같은 이름의 함수를 파라미터만 다르게 하여 정의내리는 것

    객체 인자로 보낼 때 value로 보내면 안됨.

    class HasPtr {
    public:
    	HasPtr(const std::string &s = std::string()):
    		ps(new std::string(s)), i(0) {}
    	~HasPtr() {delete ps;}
    };
    
    HasPtr f(HasPtr hp)
    {
    	HasPtr ret = hp;
    	return ret;
    }
    
    HasPtr p("some values");
    f(p); //
    HasPtr q(p); // p, q는 invalid memory를 가리킨다. 
    

    passed by value라서 hp에 p 객체가 복사되었고, 함수 스코프 벗어나는 순간, ret와 hp가 파괴되면서 해당 객체의 destructor가 호출되며 p.ps가 가리키는 string 동적객체가 파괴된다.

    13.1.5 Using = default

    명시적으로 컴파일러에게 default copy control members 생성하라고 하는 것

    13.1.6 Preventing Copies

    iostream 클래스처럼 복사가 되지 않도록 하는 방법

    • 왜 iostream은 복사 안되게 했나요?
      • 복사해서 하나의 io buffer에서 여러 객체가 읽고 쓰고하는걸 방지하기 위함

    = delete 사용

    struct NoCopy {
    	NoCopy() = default;
    	NoCopy(const NoCopy&) = delete;
    	NoCopy &operator=(const NoCopy&) = delete;
    	~NoCopy() = default;
    };
    

    destructor은 delete하면 안됨 → 객체 파괴시킬 방법이 없어지기 때문

     

    Writing Our Own swap Function

    class HasPtr {
    	friend void swap(HasPtr&, HasPtr&);
    };
    
    inline
    void swap(HasPtr &lhs, HasPtr& rhs)
    {
    	using std::swap;
    	swap(lhs.ps, rhs.ps);
    	swap(lsh.i, rhs.i);
    }
    

     

    std::swap을 쓰면 안되고 위에서 커스텀한 swap을 써야 복사과정이 안 일어나고 참조만 교환되도록 할 수 있다.

    void swap(Foo &lhs, Foo &rhs)
    {
    	using std::swap;
    	swap(lhs.h, rhs.h);
    }
    

    이 코드에서 Foo는 HasPtr을 원소로 가지고 있고, HasPtr을 교환하는 swap함수이다.

    using std::swap 해놓은 이유: HasPtr이 swap을 커스텀 정의내리지 않은 경우 대비

    왜 using std::swap을 함수 스코프 내에 선언했는데 라이브러리 swap이 안쓰이고 HasPtr의 swap이 사용되는지.

     

    rvalue reference는 곧 파괴될 객체를 참조한다.

    → 이 객체의 소유권은 줍는 사람이 임자다.

    → 객체를 훔친다

Designed by Tistory.