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 |