Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::vector as view on to raw memory

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 modify these values in place, rather than accessing them with raw pointers.

Here is an articifial example that explains the point:

size_t size = 0; int * data = get_data_from_library(size);   // raw data from library {5,3,2,1,4}, size gets filled in  std::vector<int> v = ????;                  // pseudo vector to be used to access the raw data  std::sort(v.begin(), v.end());              // sort raw data in place  for (int i = 0; i < 5; i++) {   std::cout << data[i] << "\n";             // display sorted raw data  } 

Expected output:

1 2 3 4 5 

The reason is that I need to apply algorithms from <algorithm> (sorting, swaping elements etc.) on that data.

On the other hand changing the size of that vector would never be changed, so push_back, erase, insert are not required to work on that vector.

I could construct a vector based on the data from the library, use modify that vector and copying the data back to to library, but that would be two complete copies that I'd like to avoid as the data set could be really big.

like image 472
Jabberwocky Avatar asked Feb 10 '20 13:02

Jabberwocky


People also ask

How do I allocate memory with std::vector?

An std::vector manages its own memory. You can use the reserve() and resize() methods to have it allocate enough memory to fit a given amount of items: std::vector<int> vec1; vec1. reserve(30); // Allocate space for 30 items, but vec1 is still empty.

How much memory does std::vector use?

So there is no surprise regarding std::vector. It uses 4 bytes to store each 4 byte elements. It is very efficient.

Is std::vector on heap or stack?

std::vector typically allocates memory on the heap (unless you override this behavior with your own allocator). The std::vector class abstracts memory management, as it grows and shrinks automatically if elements are added or removed.

How is a vector of vectors stored in memory C++?

The elements of a vector are stored in a dynamically allocated block of memory; otherwise, the capacity of the vector could not increase. The vector object just holds a pointer to that block.


Video Answer


1 Answers

C++20's std::span

If you are able to use C++20, you could use std::span which is a pointer - length pair that gives the user a view into a contiguous sequence of elements. It is some sort of a std::string_view, and while both std::span and std::string_view are non-owning views, std::string_view is a read-only view.

From the docs:

The class template span describes an object that can refer to a contiguous sequence of objects with the first element of the sequence at position zero. A span can either have a static extent, in which case the number of elements in the sequence is known and encoded in the type, or a dynamic extent.

So the following would work:

#include <span> #include <iostream> #include <algorithm>  int main() {     int data[] = { 5, 3, 2, 1, 4 };     std::span<int> s{data, 5};      std::sort(s.begin(), s.end());      for (auto const i : s) {         std::cout << i << "\n";     }      return 0; } 

Check it out live

Since std::span is basically pointer - length pair, you can use in a following manner too:

size_t size = 0; int *data = get_data_from_library(size); std::span<int> s{data, size}; 

Note: Not all compilers support std::span. Check compiler support here.

UPDATE

If you are not able to use C++20, you could use gsl::span which is basically the base version of the C++ standard's std::span.

C++11 solution

If you are limited to C++11 standard, you can try implementing your own simple span class:

template<typename T> class span {    T* ptr_;    std::size_t len_;  public:     span(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];     }      std::size_t size() const noexcept {         return len_;     }      T* begin() noexcept {         return ptr_;     }      T* end() noexcept {         return ptr_ + len_;     } }; 

Check out C++11 version live

like image 67
NutCracker Avatar answered Sep 19 '22 13:09

NutCracker