본문 바로가기
코드

instance in underlying array

by ehei 2021. 1. 21.
class copy_unable
{
public:
	copy_unable() {}
	copy_unable(copy_unable&) = delete;
};

int main()
{
	copy_unable c, d;

  // C2280: 'copy_unable::copy_unable(copy_unable &)': 삭제된 함수를 참조하려고 합니다.
  // std::initialize_list<copy_unable>
	auto cc = { c, d }; 

	return 0;
}

c++에서 여러 인스턴스들에게 반복된 로직을 실행시키기 위해 for 문을 사용할 수 있다. 이 때 반복시키기 위해 initialize_list나 array 등 기본 배열에 담는 경우에 복사가 생긴다.

 

이는 분명한 오버헤드이므로 회피해야 한다. 다만 언급한 사례처럼 불가피하게 중복 코드를 줄이거나 더 나은 성능 향상을 위해 쓸 경우도 있다. 이 경우에는 std::ref를 사용하여 복사 비용을 없앨 수 있다.

// ok
// std::initialize_list<std::reference_wrapper<copy_unable>>
auto cc = { std::ref(c) };​

그렇다면 ref는 어떤 구현을 사용하기에 복사가 일어나지 않을까? 코드를 보면 알 수 있는데 포인터를 취해서 저장하고, 연산자를 오버로딩해서 역참조한 값을 반환한다.

template <class _Ty>
class reference_wrapper
{
public:
    ...
    template <class _Uty, enable_if_t<conjunction_v<negation<is_same<_Remove_cvref_t<_Uty>, reference_wrapper>>,
                                          _Refwrap_has_ctor_from<_Ty, _Uty>>,
                              int> = 0>
    reference_wrapper(_Uty&& _Val) noexcept(noexcept(_Refwrap_ctor_fun<_Ty>(_STD declval<_Uty>()))) {
        _Ty& _Ref = static_cast<_Uty&&>(_Val);
        // 포인터로 저장해둔다
        // addressof는 & 연산자가 오버로딩되었어도 실제 주소를 반환해준다
        _Ptr      = _STD addressof(_Ref);
    }

    // 역참조 반환
    operator _Ty&() const noexcept {
        return *_Ptr;
    }
    ...

'코드' 카테고리의 다른 글

tuple 출력  (0) 2021.01.22
std::remove_if  (0) 2021.01.21
forward declaration of unique_ptr<T>  (0) 2021.01.21
최신 STL 배우는 방법  (0) 2020.12.15
C++ 명언  (0) 2020.12.15