How to Access the Contents of a Vector from a Pointer to the Vector in C++

How to access the contents of a vector from a pointer to the vector in C++?

There are many solutions, here's a few I've come up with:

int main(int nArgs, char ** vArgs)
{
vector<int> *v = new vector<int>(10);
v->at(2); //Retrieve using pointer to member
v->operator[](2); //Retrieve using pointer to operator member
v->size(); //Retrieve size
vector<int> &vr = *v; //Create a reference
vr[2]; //Normal access through reference
delete &vr; //Delete the reference. You could do the same with
//a pointer (but not both!)
}

Using a pointer to a std::vector to access elements in C++

Change this:

cout << x[i];

to this:

cout << (*x)[i];

or even better this:

cout << x->at(i);

since x is a pointer to the vector.

But didn't you know already? I mean you used x->size(), and not x.size()...

However, why are you passing a pointer to the function? A reference would be fine, and would allow the body of your function as it stands in your question to work fine. And since you are just printing, a const reference, would be nice, like this:

void f(const vector<int>& x)
{
// same body as in your question
}

Unrelated to your problem, but your compiler should generate a warning for your for loop, of this kind:

warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type {aka long unsigned int}' [-Wsign-compare]
for(i=0;i<x->size();i++)
~^~~~~~~~~~

Fix it by declaring i as an unsigned int, or size_t.

Access vector of vector pointers

This example shows both the syntax you where looking for, and also an example of how you should use std::vector without new/delete.

#include <iostream>
#include <vector>
#include <memory>

// using namespace std; <== teach yourself NOT to do this.
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

void access_pointers_in_2d_vector()
{
std::vector<std::vector<int>*> values; // don't call your variables main!

for (int j = 0; j < 3; j++)
{
std::vector<int>* myvector = new std::vector<int>;
values.push_back(myvector);
}

values[0]->push_back(1);
values[0]->push_back(4);
values[1]->push_back(6);
values[1]->push_back(7);
values[1]->push_back(8);
values[2]->push_back(3);

for (int j = 0; j < 3; j++)
{
for (uint32_t i = 0; i < values[j]->size(); i++)
{
//==================================================================
// this is the syntax you're looking for
// first dereference the pointer then use operator[]
std::cout << (*values[j])[i] << " ";
//==================================================================
}

std::cout << "\n";
}

// don't forget to cleanup your memory!
// if you typed new somewhere then there should
// ALWAYS be a matching delete in your code too!
for (int j = 0; j < 3; j++)
{
delete values[j]; // <<==== !!!!!!!
}
}

// for dynamic memory managment new/delete aren't recommended anymore.
// use std::unique_pointer (or if your design really requires it std::shared_ptr)
void using_unique_pointer()
{
// If you really need pointers, use std::unique_ptr
// it will prevent you from introducing memory leaks
const std::uint32_t size = 3ul;
std::vector<std::unique_ptr<std::vector<int>>> values(size);
for (auto& p : values)
{
p = std::make_unique<std::vector<int>>();
}

values[0]->push_back(1);
values[0]->push_back(4);
values[1]->push_back(6);
values[1]->push_back(7);
values[1]->push_back(8);
values[2]->push_back(3);

// output loop is same as for normal pointers.
// no need to call delete, std::unique_ptr will do that for you
}

void without_pointers()
{
// However your whole code in idiomatic c++ should look like this.
// https://en.cppreference.com/w/cpp/container/vector/vector constructor (10)
// https://en.cppreference.com/w/cpp/language/range-for these loops avoid bugs related to
// letting indices go out of bounds.

std::cout << "\nusing (nested) initializer list and range based for loops : \n";
std::vector<std::vector<int>> rows{ {1,4}, {6,7,8}, {3} };
for (const auto& row : rows)
{
for (const auto& value : row)
{
std::cout << value << " ";
}
std::cout << "\n";
}
}

int main()
{
access_pointers_in_2d_vector();
using_unique_pointer();
without_pointers();
return 0;
}

Dereference vector pointer to access element

10000 ints will not be copied. Dereferencing is very cheap.

To make it clear you can rewrite

int a = (*vecPtr)[i];

as

vector<int>& vecRef = *vecPtr; // vector is not copied here
int a = vecRef[i];

In addition, if you are afraid that the whole data stored in vector will be located on the stack and you use vector<int>* instead of vector<int> to avoid this: this is not the case.
Actually only a fixed amount of memory is used on the stack (about 16-20 bytes depending on the implementation), independently of the number of elements stored in the vector.
The vector itself allocates memory and stores elements on the heap.

getting pointers to vector elements

When a new element is added to a vector then the vector can be reallocated. So the previous values of pointers to the elements of the vector can be invalid.

You should at first reserve enough memory for the vector preventing the reallocation.

edge_vec2.reserve( SomeMaxValue );

How to read element from a vector pointer?

You need to dererference the pointer before accessing the array. Just like you are doing with the -> operator to get the size.

(*test.frames)[0].w;

You could use the -> operator to also access the [] operator method, but the syntax isn't as nice:

test.frames->operator[](0).w;

If you want to be able to use [] directly like a true vector syntactically, then you can either allow the frames member to take a copy of the vector, you it can reference the vector. Or, you can overload [] on the animstruct itself to use the [] syntax on your test variable.

Copy:

struct animstruct { vector<framestruct> frames; };
animstruct test;
void init_anim(){ test.frames = some_animation; }

test.frames[0].w;

Reference:

struct animstruct { vector<framestruct> &frames;
animstruct (vector<framestruct> &f) : frames(f) {} };
animstruct test(some_animation);
void init_anim(){}

test.frames[0].w;

Overload:

struct animstruct { vector<framestruct> *frames;
framestruct & operator[] (int i) { return (*frames)[i]; } };
animstruct test;
void init_anim(){ test.frames = &some_animation; }

test[0].w;

Returning a pointer to a vector element in c++

Return the address of the thing pointed to by the iterator:

&(*iterator)

Edit: To clear up some confusion:

vector <int> vec;          // a global vector of ints

void f() {
vec.push_back( 1 ); // add to the global vector
vector <int>::iterator it = vec.begin();
* it = 2; // change what was 1 to 2
int * p = &(*it); // get pointer to first element
* p = 3; // change what was 2 to 3
}

No need for vectors of pointers or dynamic allocation.

In C++, how can I get a pointer into a vector?

Try a std::pair< vector*, int>, as neither the position of the vector nor the index of the element changes.

Or, as a class:

template<class T> class VectorElementPointer
{
vector<T>& vectorref;
typename vector<T>::size_type index;
public:
VectorElementPointer(vector<T>& vref, typename vector<T>::size_type index):vectorref(vref),index(index){}
T& operator*() const {return vectorref[index];}
T* operator->() const {return &vectorref[index];}
};

This is the easiest solution that comes to my mind, as neither the STL nor Boost contains anything to do it easier.



Related Topics



Leave a reply



Submit