-5

I have a templated class I use to create and manipulate a jagged array. I can create the jagged array; add elements; remove them; modify them; print the jagged array, etc. It seems to work at least as far my testing so far, until I try to pass a previously created jagged array to it to create another. My class currently takes what is passed, and creates what appears to be a clone, but it ends up being an alias for the same memory space. So, when I go to make a change in what I think is the clone, I end up making the change in 'both' of them. I'm kind of lost and was wondering if anyone might be able to give me some pointers?

  • Welcome to SO! Without code nobody can guess the fix. Please, add a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Ripi2 Sep 27 '19 at 01:10
  • 1
    By replacing it with a [`std::vector`](https://en.cppreference.com/w/cpp/container/vector) would be my suggestion. `std::vector` is [Rule of Five](https://en.cppreference.com/w/cpp/language/rule_of_three) observant, so it will handle all of the monkey-work for you. – user4581301 Sep 27 '19 at 01:32
  • By the way, you've accidentally discovered the Rule of Five's somewhat simpler brother, the Rule of Three. [Here is an answer to a similar question that you should be able to derive inspiration from](https://stackoverflow.com/a/32360389/4581301) – user4581301 Sep 27 '19 at 01:37

1 Answers1

0

It's hard to tell exactly what your problem is without a code example, but it sounds like your array contains pointers. For example:

std::vector<int*> original;
original.push_back(new int[]{1}); // note: for demo only (`new` without `delete` is bad)
std::vector<int*> copy = original;
copy[0][0] = 2; // now original[0][0] also equals 2

Since copy contains the same pointers as original, original[0] and copy[0] are the same pointer, and so original[0][0] and copy[0][0] refer to the same object.

You can fix this by copying the values being pointed to, rather than the pointers themselves, and storing pointers to the copies in your new array. In my example, the easiest way would be to use std::vector<int> instead of int*:

std::vector<std::vector<int>> original;
original.push_back({1});
std::vector<std::vector<int>> copy = original;
copy[0][0] = 2; // original[0][0] still equals 1
Joseph Thomson
  • 9,888
  • 1
  • 34
  • 38
  • This is a half measure that's kind of pointless. Asker's whole problem goes away with a `vector` of `vectors`. – user4581301 Sep 27 '19 at 02:40
  • @user4581301 I'm confused. The solution in my example is exactly that. What exactly is a half measure? – Joseph Thomson Sep 27 '19 at 09:29
  • `vector` is only marginally better than `int **` and still requires observance of the The Rule of Three to be safely copyable. `vector` provides the same jagged array and does not need any help from the programmer because the Rule of Three is baked into `vector`. If you're going to use `vector` for half of the job, you might as well use it for the other half as well. – user4581301 Sep 27 '19 at 15:57
  • @user4581301 I can only assume that you didn't read my answer properly. I gave the example of `vector` because it sounds like the OP was doing something like that. Then I suggested that an easy solution would be to use `vector>` to make sure the underlying data is copied. In other words, I am suggesting exactly what you are suggesting. – Joseph Thomson Sep 27 '19 at 16:50
  • I plead guilty to that, but a recommendation: Order the answer to lead with the correct approach.Go back to explain the reasoning if necessary. – user4581301 Sep 27 '19 at 18:00
  • And an apology I don't think came through well in that last comment is in order. You are correct. I turned off my brain after the first code segment. I am completely in the wrong here. – user4581301 Sep 27 '19 at 19:24
  • @user4581301 Don't worry about it. Feedback noted :) – Joseph Thomson Sep 28 '19 at 01:16