Using std::vector as view on to raw memory

后端 未结 10 1706
感动是毒
感动是毒 2021-01-31 13:34

I\'m using a external library which at some point gives me a raw pointer to an array of integers and a size.

Now I\'d like to use std::vector to access and

10条回答
  •  误落风尘
    2021-01-31 13:47

    The problem is that std::vector has to make a copy of the elements from the array you initialize it with as it has the ownership of the objects it contains.

    To avoid this, you can use a slice object for an array (i.e., similar to what std::string_view is to std::string). You could write your own array_view class template implementation whose instances are constructed by taking a raw pointer to an array's first element and the array length:

    #include 
    
    template
    class array_view {
       T* ptr_;
       std::size_t len_;
    public:
       array_view(T* ptr, std::size_t len) noexcept: ptr_{ptr}, len_{len} {}
    
       T& operator[](int i) noexcept { return ptr_[i]; }
       T const& operator[](int i) const noexcept { return ptr_[i]; }
       auto size() const noexcept { return len_; }
    
       auto begin() noexcept { return ptr_; }
       auto end() noexcept { return ptr_ + len_; }
    };
    

    array_view doesn't store an array; it just holds a pointer to the beginning of the array and the length of that array. Therefore, array_view objects are cheap to construct and to copy.

    Since array_view provides the begin() and end() member functions, you can use the standard library algorithms (e.g., std::sort, std::find, std::lower_bound, etc.) on it:

    #define LEN 5
    
    auto main() -> int {
       int arr[LEN] = {4, 5, 1, 2, 3};
    
       array_view av(arr, LEN);
    
       std::sort(av.begin(), av.end());
    
       for (auto const& val: av)
          std::cout << val << ' ';
       std::cout << '\n';
    }
    

    Output:

    1 2 3 4 5
    

    Use std::span (or gsl::span) instead

    The implementation above exposes the concept behind slice objects. However, since C++20 you can directly use std::span instead. In any case, you can use gsl::span since C++14.

提交回复
热议问题