How to Get Std::Vector Pointer to the Raw Data

How to get std::vector pointer to the raw data?

&something gives you the address of the std::vector object, not the address of the data it holds. &something.begin() gives you the address of the iterator returned by begin() (as the compiler warns, this is not technically allowed because something.begin() is an rvalue expression, so its address cannot be taken).

Assuming the container has at least one element in it, you need to get the address of the initial element of the container, which you can get via

  • &something[0] or &something.front() (the address of the element at index 0), or

  • &*something.begin() (the address of the element pointed to by the iterator returned by begin()).

In C++11, a new member function was added to std::vector: data(). This member function returns the address of the initial element in the container, just like &something.front(). The advantage of this member function is that it is okay to call it even if the container is empty.

Get pointer to raw data in set like &(vector[0])

No, this is not necessarily possible. The C++ ISO standard explicitly guarantees contiguous storage of elements in a std::vector, so you can safely take the address of the first element and then use that pointer as if you were pointing at a raw array. Other containers in the standard library do not have this guarantee.

The reason for this is to efficiently support most operations on a std::set, the implementation needs to use complex data structures like balanced binary search trees to store and organize the data. These structures are inherently nonlinear and require nodes to be allocated and linked together. Efficiently getting this to work with the elements in a flat array would be difficult, if not impossible, in the time constraints laid out by the standard (amortized O(log n) for most operations.)

EDIT: In response to your question - there is no way to build a std::vector from a std::set without some code somewhere iterating over the set and copying the elements over. You can do this without explicitly using any loops yourself by using the std::vector range constructor:

std::vector<T> vec(mySet.begin(), mySet.end());

Hope this helps!

Get raw data pointer from empty std::vector

Just perform the check inside a conditional operator:

int const * a = v.empty() ? NULL : &v[0];

This has the added benefit over data() that you can check from the pointer itself whether the vector was empty: if it was, a is null.

Using std::vector as view on to raw memory

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 <cstdint>

template<typename T>
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<int> 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.

Raw pointer, smart pointer or std::vector for low-level container data in C++

I would use std::vector because it solves memory allocation, deallocation, indexing, copying, etc.. Unless you will be using "millions" of matrices at the same time, the extra member (capacity) is probably not relevant.

In any case, optimizing the library for speed is the last thing you want to do -- after you can test the actual speed of your initial implementation. Then you can decide if it is worth spending time to effectively duplicate std::vector functionality with your own implementation.

Is accessing the raw pointer after std::vector::reserve safe?

No, it is not safe.

After a reserve(), the vector is guaranteed not to reallocate the storage until the capacity() is reached.

However, the standard doesn't say what the vector implementation can do with the storage between size() and capacity(). Perhaps it can be used for some internal data - who knows? Perhaps the address space is just reserved and not mapped to actual RAM?

Accessing elements outside of [0..size) is undefined behavior. There could be some hardware check for that.

Is it possible to get a raw pointer to std::vector unsigned int data?

So two things:

  1. You can access the contiguous memory of a vector with std::vector::data() or &vec.front().

  2. If you do that in the code shown above, you'll be returning a pointer to data that disappears when the function returns (the vector's destructor will run, and the data will be freed).



Related Topics



Leave a reply



Submit