2

Let's say I have a couple of vectors of integers and a pointer to a vector of integers. How would I go about changing the value of one element of the pointer to be the address in one of the other vectors of integers?

The context for this is that I've built a class that lets me bring in my desktop into the unreal engine, however on each tick it has to assign a form of vector that contains a struct to the values of another data class each tick, I instead wish to copy the memory addresses over for only a few of the elements (the pixel colour values) so I don't waste time by having to do a copy twice (which for a desktop image is millions of operations)

#include <iostream>
#include <vector>

using namespace std;

// Print function
void PrintVector(vector<int> v)
{
 for( int i = 0; i < v.size(); i++ )
 {
 cout << v[i] << ", ";
 }
 cout << endl;
}

int main()
{

    vector<int> vector1;
    vector<int> vector2;
    vector<int> *ptrvector;

    //Do some assignment so the vectors have values
    for( int i = 0; i<3; i++)
    {
        vector1.push_back(i);
        vector2.push_back(2*i);
    }
    //Assign the pointer to the address of vector1.
    ptrvector = &vector1;

    //Print out:
    PrintVector(vector1);  // (1,2,3)
    PrintVector(vector2);  // (2,4,6)
    PrintVector(*ptrvector); // (1,2,3)
    // We should see that lines 1 and 3 are the same

    //BROKEN BIT::

    //Ideally want something like
    ptrvector[0] = &vector2[2];
    PrintVector(*ptrvector); // (6,2,3);

    //Such that if I were to do this:
    vector2[2] = 20;
    PrintVector(*ptrvector); // It should change as a side effect: (20,2,3)


}

BONUS QUESTION:

Let's say I have this:

TArray<FColor> ColorData;
TArray<FColor> *ptrColorData
//Where TArray is essentially a vector. FColor is a struct with members (R,G,B,A)

//ColorData is initialised somewhere and we set the ptrColorData to the address
ptrColorData = &ColorData;

//Somewhere down the line we have a long loop whereby we do
ColorData[i].B = somedata[i];
ColorData[i].G = somedata[i+1];
ColorData[i].R = somedata[i+3];

//somedata is updated per tick, asigning ColorData per tick as well slows it down.
// I wish to be able to do something on the lines of this

ptrColorData[i].B = &somedata[i];
ptrColorData[i].G = &somedata[i+1];
ptrColorData[i].R = &somedata[i+3];

// this is only called once to initialize. Because the memory address
//is unchanging and somedata changes by functions on its own it means when
// I tell my unreal engine to update a texture by passing (*ptrColorData)
// to a function it automatically has the new data when that function is
// next called.
Artamentix
  • 21
  • 3
  • To address elements in a `std::vector` by pointer is not impossible but I wouldn't recommend to do so. Please, be aware that as soon as you add elements to a vector it might re-allocate its internal storage. Hence, all pointers would become broken (dangling). Better is to address elements in a vector by index. – Scheff's Cat Dec 14 '18 at 06:34
  • If you insist to address vector elements by pointers... You can get the address of a vector element simply by using the address operator (`operator&()`) as usual. E.g. `std::vector vec = { 1, 2, 3, 4, 5 }; int *pA = &vec[2]; // pA points to vec[2] now.` – Scheff's Cat Dec 14 '18 at 06:37
  • May be, I got your intention wrong. `ptrvector[0] = &vector2[2];` This would work with the the correct indirection: `(*ptrvector)[0] = vector2[2];` Please, be aware a pointer to vector is not a vector of pointers. I believe you have confused this... – Scheff's Cat Dec 14 '18 at 06:42
  • @Scheff Thank you! I wasn't quite aware of the correct notation for the pointers. This correctly updates the pointer's address, however if I were to say assign `vector2[2] = someothernumber` the address of `vector2[2]` changes which is what I'm trying to avoid. Might be thinking of something impossible here ( I don't know the full details in how it allocates memory ) but the intention was that if the memory address was unchanging I could shave off a few million operations as my set-up pointer to a vector would have its values at the addresses update without having to do an additional copy. – Artamentix Dec 14 '18 at 07:25
  • "however if I were to say assign `vector2[2] = someothernumber` the address of `vector2[2]` changes" - no, it does not change its address – Fureeish Dec 14 '18 at 08:01
  • @Fureeish my mistake, I was trying to check why updating vector[2] wasn't updating *ptrvector and was checking the memory addresses of each vector, turns out I had a typo with it, though the problem here I think is by using (*ptrvector)[0] all I'm doing is assigning what ptrvector is pointing to at it's 0th entry (the value) and not the memory address itself so updating fails. – Artamentix Dec 14 '18 at 20:36

1 Answers1

2

This should produce the output you want, but be aware. As stated in the comments, the addresses stored int the std::vector<int*> should be considered invalid if you change the size of vector1 or vector2 in any way and if you reorder the elements in the original vectors, your pointers will point to the wrong values. I also removed using namespace std;. See: Why is “using namespace std” considered bad practice?.

#include <iostream>
#include <vector>

// Print function
void PrintVector(std::vector<int> v) {
    for(auto x : v) std::cout << x << ", ";
    std::cout << "\n";
}

void PrintVector(std::vector<int*> v) {
    for(auto x : v) std::cout << *x << ", ";
    std::cout << "\n";
}

int main() {
    std::vector<int> vector1;
    std::vector<int> vector2;
    std::vector<int*> ptrvector; // pointers to the elements in vector1/2

    //Do some assignment so the vectors have values
    for( int i = 1; i<=3; i++) {
        vector1.push_back(i);
        vector2.push_back(2*i);
    }
    // Add pointers in ptrvector to the addresses in vector1.
    ptrvector.reserve(vector1.size());
    for(auto& r : vector1)
        ptrvector.emplace_back(&r);

    //Print out:
    PrintVector(vector1);   // (1,2,3)
    PrintVector(vector2);   // (2,4,6)
    PrintVector(ptrvector); // (1,2,3)

    ptrvector[0] = &vector2[2];
    PrintVector(ptrvector); // (6,2,3);

    vector2[2] = 20;
    PrintVector(ptrvector); // (20,2,3)
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108