NeuroWhAI의 잡블로그

[C++] get/return_temporary_buffer, uninitialized_*에 대하여 본문

개발 및 공부/언어

[C++] get/return_temporary_buffer, uninitialized_*에 대하여

NeuroWhAI 2018. 11. 14. 21:23


memory 헤더에 있는 이 함수들은 초기화 되지 않은 메모리에 관한 기능이 있습니다.

초기화 되지 않았다는 것은 생성자가 호출되지 않았다는 것이죠.

get_temporary_buffer는 메모리를 할당하며

return_temporary_buffer는 메모리를 해제합니다.

uninitialized_*는 초기화되지 않은 메모리에 대해 생성자를 호출하며 특정 알고리즘을 수행합니다.


예시를 봅시다. (C++17 이상에서만 컴파일 됨)

#include <iostream>
#include <algorithm>
#include <memory>

class Foo
{
public:
    explicit Foo(int data) : data(data)
    { 
        std::cout << "Foo()" << std::endl;
    }
    ~Foo() { std::cout << "~Foo()" << std::endl; }
    
    int data;
};
 
int main()
{
    std::cout << "Allocate" << std::endl;
    auto [p, sz] = std::get_temporary_buffer<Foo>(4);
 
    std::cout << "Fill" << std::endl;
    std::uninitialized_fill(p, p+sz, 42);
    
    std::cout << "Show" << std::endl;
    for (Foo* i = p; i != p+sz; ++i) {
        std::cout << i->data << std::endl;
    }
 
    std::cout << "Destroy" << std::endl;
    std::destroy(p, p+sz);
    
    std::cout << "Deallocate" << std::endl;
    std::return_temporary_buffer(p);
    
    return 0;
}
Allocate
Fill
Foo()
Foo()
Foo()
Foo()
Show
42
42
42
42
Destroy
~Foo()
~Foo()
~Foo()
~Foo()
Deallocate

보시면 Allocate만으로는 생성자가 호출되지 않았고 uninitialized_fill 함수가 수행되면서 호출이 된 것을 알 수 있습니다.

destroy는 그냥 소멸자를 호출해주는 함수입니다.

return_temporary_buffer는 따로 소멸자를 호출해주지 않고 메모리만 해제하기 때문에 destroy 작업이 필요합니다.


잠깐 uninitialized_fill의 구현 예시를 봅시다.

template<class ForwardIt, class T>
void uninitialized_fill(ForwardIt first, ForwardIt last, const T& value)
{
    typedef typename std::iterator_traits<ForwardIt>::value_type Value;
    ForwardIt current = first;
    try {
        for (; current != last; ++current) {
            ::new (static_cast<void*>(std::addressof(*current))) Value(value);
        }
    }  catch (...) {
        for (; first != current; ++first) {
            first->~Value();
        }
        throw;
    }
}

중요한 곳은 for 부분 입니다.

보시면 current 반복자가 가리키는 객체의 주소에 value(예시에선 42)를 인수로 하여 생성자를 호출하는 것을 볼 수 있습니다.


uninitialized_*에는 fill 말고도 copy, move, default_construct 등이 있으며 C++17에서 다수 추가되었습니다.


끝!

'개발 및 공부 > 언어' 카테고리의 다른 글

[Rust] Lifetime의 한계  (0) 2018.11.18
[C++] Designated initializers  (0) 2018.11.17
[Rust] Send와 Sync  (0) 2018.11.12
[C/C++] a[i] == i[a] ???  (0) 2018.11.06
[C++] STL nth_element 알고리즘 설명 및 예시  (3) 2018.11.01


Comments