[모던C++입문] 2.3 값 설정: 생성자 및 할당 연산자

짜장범벅·2022년 6월 4일
0

모던CPP입문

목록 보기
4/11

2.3.3 초기화 리스트

초기화 리스트를 사용하려면 <initializer_list> 헤더를 포함해야 한다.

#include <initializer_list>
#include <algorithm>

class vector{
    ...

    vector(std::initializer_list<double> values)
        : my_size(values.size()), data(new double[my_size])
        {
            std::copy(std::begin(values), std::end(values), std::begin(data));
        }

        vector& operator=(std::initializer_list<double> values)
        {
            assert(my_size == values.size());

            std::copy(std::begin(values), std::end*(values), std::begin(data));

            return *this;
        }
}

2.3.4 유니폼 초기화(생략)

2.3.5 이동 문법

복사하는 양이 많은 경우 얕은 복사(Shallow Copy)를 사용한다. 또한 일번작으로 깊은 복사(Deep Copy)도 제공하고 있다.

2.3.5.1 이동 생성자

class vector{
    ...
    vector(vector&& v)
        : my_size(v.my_size), data(v.data)
        {
            v.data = 0;
            v.my_size = 0;
        }
};

이동 생성자는 원본에서 데이터를 훔쳐 빈 상태로 둔다. 여기서 vector&& v와 같은 Rvalue 레퍼런스는 이름이 있는 Lvalue다.

C++11에서는 두 개의 앰퍼샌드 &&로 표시된 Rvalue 래퍼런스를 도입한다. 이름값이 있는 Lvalue는 Rvalue 레퍼런스로 전달할 수 없다.

Rvalue로 함수에 전달한 개체는 함수로 반환한 뒤 만료되었다고 간주한다.

2.3.5.2 이동 할당 연산자

class vector {
    ...
    vector& operator=(vector&& src)
    {
        assert(my_size == 0 || my_size == src.my_size);

        std::swap(data, src.data);
    }
};

이렇게 하면 원본 src를 파괴했을 때 해체 작업을 수행하므로 기존 데이터를 해제하지 않아도 된다.

2.3.5.3 복사 생략

위 두 함수는 생각보다 자주 호출되지 않는다. 그 이유는 최신 컴파일러가 데이터를 훔치는 것 보다 더 나은 최적화를 제공하기 때문이다.

inline vector ones(int n) {
    vector v(n);

    for (unsigned i=0; i<n; ++i)
        v[i] = 1.0;

    return v;
}

...

vector w(ones(7));

위 코드에서 컴파일러는 v를 생성하고 함수 끝에서 w로 복사하는 대신 w를 즉시 생성하고 그곳에서 모든 연산을 수행한다.

profile
큰일날 사람

0개의 댓글