Selective shallow copy from one array to another
Asked Answered
M

3

6

Assuming I have 2 array of different size i.e

int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *arr2 = new int[5];

I want to shallow copy some of them, Deep copy equivalent would be

int j =0;    
if(!(i%2))
    {
        arr2[j]=arr[i];
        j++;
    }

Right now a print of arr2 will output : 0, 2, 4, 6 ,8

The reason I want to shallow copy is because I want arr2 to update with any changes to arr.

That is if I loop and square all the elements in arr

I want arr2 to output : 0, 4, 16, 36 ,64

These 2 arrays are part of the same class, one is my polygonal information, and the other part is data driven. arr is actually 4000+ elements in size, and arr2 is close to 3000. At the moment my algorithm works great with deep copy. but because I need to deep copy 3000 elements per update frame, i am wasting resources and was wondering if i could somehow do this via shallow copy so I don't have to have to update arr2 every frame. The way my code needs it to work, arr actually has repeated values of arr2. arr2 is a list of points that is animated. then the data is duplicated to arr which hold the positional data for vertices. this is because arr contains multiple bezier patches, some of them share one edge or more with another patch. but i want that to be ignored when animating else there are breaks in the surface.

It is important that the copy involves indices like

arr2[j]=arr[i];

because that is how my code is setup. And that the operation be low load.

Meggs answered 31/7, 2014 at 4:29 Comment(9)
For a C++ solution, you should write a std::array-like class, whic has operator[] which does the right thing of referencing an original. Sort of like model-view thing.Cress
You just said that arr2[j] = arr[i]; is deep copy, and then you said it's important that the shallow copy is arr2[j]=arr[i];. That doesn't make sense. Is there a problem with doing int *arr2 = arr; ?Anzac
@Cress A class would just be doing the deep copy internally still couses performance issues.Meggs
@MattMcNabb yes there is. arr is a larger array than arr2. so If i do *arr2 = arr; i loose data. And the tricky part is arr contains repeated data from arr2 in a specific order.Meggs
@Meggs Umm, I meant a class which doesn't do any copying, deep or shallow, but just accesses the actual array. One-way (read-only) or two-way, depending on requirements.Cress
@Cress The data relation between them is quite complicated. I am stitching 4*4 3D vertices patches together at the edges. and there are hundreds of them. Each frame i make changes (animate) to the smaller set, which is already 30k+ assignment operations not to mention all of its calculations. if i do any sort of assignment at all i will have to do at least twice that. This has to be done 60 time per 1000 cpu clock cycle. That is why i want to avoid copying it over at all. I'd rather have an array of pointers pointing to the set like Krypton suggested below.Meggs
Since you're still talking about copying, I wrote an answer to demonstrate what I mean (note, no copying!). Anyway, to know which is faster, the only way is to benchmark (with compiler optimizations turned on), but extra memory access of pointer array approach is not cheap, that's for sure.Cress
@Meggs int *arr2 = arr; is different from *arr2 = arr. No data is lost, you can access all of arr through arr2Anzac
@Meggs I looked at hyde's answer which make use of C++ referencing feature. Mine is pure C. You can consider his approach if you have C++ as development environment.Biggin
B
6

You will need an array of integer pointers for that.

int *arr2[5];

for (int i = 0, j = 0; i < 10; i++) {
    if (!(i%2)) {
        arr2[j]= &arr[i];
        j++;
    }
}

So you need to set each element of arr2 to point to corresponding element in arr by arr2[j]= &arr[i];

When you need to access element in arr2, you call some thing like: int a = *arr2[j];

Later on let say you change arr[0] to 10 arr[0] = 10; then int a = *arr2[0]; will give you 10.

Biggin answered 31/7, 2014 at 4:45 Comment(5)
It should be sizeof(arr) / sizeof(*arr)... (or the more intuitive arr.size() if arr would be a std::array)Feucht
I see, so instead of a array i keep an array of pointers instead. So then i just dereference them when i need the value. That makes perfect sense. Just one question however, is there anyway to new an array of int pointers. I'm not sure about the syntax.Meggs
I need arr2 to be dynamically allocated. I tried new *int[5] and new int*[5], but it does not seem to be right. Worst case i would just make arr2 much bigger than it will ever needs to be, and use another a variable to keep track of its usable size. But i'd rather not. Thank you for your answer by the way, you drastically increased my frame rates.Meggs
never mind i figured it out, i need int **arr2 = new int*[5] Thank you for all your helpMeggs
Glad to hear that you figured it out. C/C++ is very interesting to learn, you'll get addicted on your way learning it.Biggin
C
0

As an alternative to the pointer array approach, here's a crude C++03 example of how to this programmatically. Which one is better depends on how complex the operator[] here needs to be in the real use case, and how much smaller the 2nd array is (ie. how much extra memory it needs, causing cache misses etc).

#include <iostream>

class c_array_view  {
public:
    c_array_view(int *array) : array_(array) {}
    int& operator[](size_t index) { return array_[index*2]; }

    static size_t convert_length(size_t original) { return original / 2; }

private:
    int *array_;
};

int main()
{
    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    size_t arr_len = sizeof arr / sizeof arr[0];

    c_array_view arr2(arr);
    size_t arr2_len = arr2.convert_length(arr_len);

    for(unsigned i = 0; i < arr_len; ++i) {
        std::cout << "arr: " << i << " = " << arr[i] << std::endl;
    }
    std::cout << std::endl;

    for(unsigned j = 0; j < arr2_len; ++j) {
        std::cout << "arr2: " << j << " = " << arr2[j] << std::endl;
    }
    std::cout << std::endl;

    arr2[2] = 42;
    std::cout << "modifeid arr2[2] to 42, now arr[4] = " << arr[4] << std::endl;

    return 0;
}

The c_array_view could be turned into a template, a nice general purpose class which would take the mapping function as a C++11 lambda, etc, this just demonstrates the principle.

Cress answered 31/7, 2014 at 11:7 Comment(0)
U
-2

if you want squares then you should not do arr2[j]=arr[i]. The correct answer would be

arr2[j]=arr[i]*arr[i];
Unhandy answered 31/7, 2014 at 5:12 Comment(1)
OP wants arr2 to reference arr. The squaring is just an example.Canescent

© 2022 - 2024 — McMap. All rights reserved.