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.

new2code
  • 61
  • 4
  • 1
    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. – hyde Jul 31 '14 at 04:51
  • 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;` ? – M.M Jul 31 '14 at 05:03
  • @hyde A class would just be doing the deep copy internally still couses performance issues. – new2code Jul 31 '14 at 10:31
  • @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. – new2code Jul 31 '14 at 10:34
  • @new2code 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. – hyde Jul 31 '14 at 10:37
  • @hyde 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. – new2code Jul 31 '14 at 10:50
  • 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. – hyde Jul 31 '14 at 11:11
  • @new2code `int *arr2 = arr;` is different from `*arr2 = arr`. No data is lost, you can access all of `arr` through `arr2` – M.M Jul 31 '14 at 11:28
  • @new2code 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. – Krypton Aug 01 '14 at 02:28

3 Answers3

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.

Krypton
  • 3,337
  • 5
  • 32
  • 52
  • It should be `sizeof(arr) / sizeof(*arr)`... (or the more intuitive `arr.size()` if `arr` would be a `std::array`) – Jarod42 Jul 31 '14 at 09:08
  • 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. – new2code Jul 31 '14 at 10:22
  • 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. – new2code Jul 31 '14 at 10:38
  • 1
    never mind i figured it out, i need int **arr2 = new int*[5] Thank you for all your help – new2code Jul 31 '14 at 21:00
  • Glad to hear that you figured it out. C/C++ is very interesting to learn, you'll get addicted on your way learning it. – Krypton Aug 01 '14 at 02:09
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.

hyde
  • 60,639
  • 21
  • 115
  • 176
-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];
Tamir Abutbul
  • 7,301
  • 7
  • 25
  • 53