37

Possible Duplicate:
How are C array members handled in copy control functions?

I would guess the implicit copy constructor (generated by compiler) would copy pointer data members if they are declared as pointer.

I'm not sure what happens to array data members.

Does the implicit copy constructor copy array members correctly? What about the assignment operator?

For instance:

char mCharArray[100];
int mIntArray[100];   

Would the mCharArray and mIntArray be copied correctly?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
eugene
  • 39,839
  • 68
  • 255
  • 489

4 Answers4

67

Yes and yes is the answer. This is also true of structs in C.

typedef struct {
    int a[100];
} S;

S s1;
s1.a[0] = 42;
S s2;
s2 = s1;    // array copied
  • 1
    I hope your answer to be correct. other people's answer confuses me though :( – eugene Apr 18 '11 at 08:31
  • 2
    @Eugene People do seem to be making heavy going of this. My answer is correct - as I said, C works in exactly the same way. –  Apr 18 '11 at 09:46
  • 1
    people are making heavy going of this because they're trying to explain the slightly-more-complicated case of structures containing pointers and references. It's not clear that that case is necessary to answer the question, but it's close enough that other answers obviously felt it better to let Eugene know about that too.... – Tony Delroy Apr 18 '11 at 10:23
  • @Tony Unfortunately, all the other answers except yours are factually incorrect, and I found yours hard to understand. I also don't think we should be encouraging the use of strdup! –  Apr 18 '11 at 10:34
  • true about strdup... I kept thinking - I should change this to new char[] and a copy, but the extra copy step seemed so much extra pain today... thank god for `std::string`. You're shaming me into fixing it! :-) – Tony Delroy Apr 18 '11 at 11:29
  • http://www.geeksforgeeks.org/are-array-members-deeply-copied/ – FaceBro Sep 02 '17 at 10:49
  • 4
    I think it'd be worth adding `s2.a[0] = 43; std::cout << s1.a[0] << std::endl; // 42` just to illustrate that it's actually copied, not just the pointer to the data. – Nic Dec 28 '18 at 16:15
8

Just to make it as clear as possible:

struct X
{
    char data_[100];
};

X a, b;
a.data_[10] = 'x';
b = a;
// here, b.data_[n] == a.data_[n] for 0 <= n < 100, so b.data_[10] == 'x'

BUT, the potentially nasty case is for pointers and references:

struct X
{
    char* data_[100];
};

X a, b;
a.data_[10] = new char[6]; // a character array on the heap
strcpy(a.data_[10], "hello"); // put some text into it...
b = a;
// here, b.data_[n] == a.data_[n] for 0 <= n < 100
//   so b.data_[10] == a.data_[10] == same character array containing "hello"
// BUT...
b.data_[10][2] = 'L';  // change text to "heLlo" via b.data_[10] pointer...
// here, a.data_[10][2] will be 'L' too, as a.data_[10] and b.data_[10] both point
// to the same underlying heap memory returned by new above...
delete[] a.data_[10];  // ok...
std::cout << b.data_[10];  // NOT ok - this memory's been deallocated!
delete[] b.data_[10];  // NOT ok - this memory's (already) been deallocated!

Hopefully that helps illustate the issue.

Consider one way to make the structure more "copy-safe":

struct X
{
    X(const X& rhs)
    {
        for (int i = 0; i < 100; ++i)
            if (rhs.data_[i])
            {
               // deep copy of pointed-to text...
               data_[i] = new char[strlen(rhs.data_[i]) + 1];
               strcpy(data_[i], rhs.data_[i]);
            }
            else
               data_[i] = NULL;
    }
    char* data_[100];
};

Here, the copy-constructor makes X b = a safer and more intuitive because it makes its own copy of all the string data and has no further dependency on or connection to the copied X object, but this is slower and potentially more wasteful of memory.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

"implicit copy constructor(generated by compiler)" - does a shallow copy for all variables.

Sujay Ghosh
  • 2,828
  • 8
  • 30
  • 47
  • 2
    what do you mean by shallow copy here? elements in the array in questions are shallow copied? – eugene Apr 18 '11 at 08:30
  • 1
    A shallow copy means it doesn't "deep copy" pointed-to or referenced values. In other words, if you shallow-copy a pointer or reference, you end up with two pointers or references to the same object (and may need to be careful not to free it prematurely or twice). Deep copies would copy/clone the pointed-to or referenced object too, so the objects containing the pointer/reference have their "own" copy, independent of the copied-from object. – Tony Delroy Apr 18 '11 at 08:34
  • @Tony: my original question can be rephrased as "does array members are shallow copied or pointer to array is copied?" I'm not asking if members of array are deep copied. – eugene Apr 18 '11 at 08:40
  • @Eugene: the best way to think of it is as per two variables: if you have `X a = ...; X b = a;`, then b is not deep-copied unless the X object supplies that semantic behaviour (e.g. int, double, vectors, strings but NOT plain pointers or references). The exact same thing is true if a and b are arrays and member variables, and applies on a element by element basis. The rules are consistent. – Tony Delroy Apr 18 '11 at 08:53
-3

Yes. Copy constructor and Assignment operators are in-built provided in C/C++. They do byte by byte copy (which is not good for larger arrays, as it will cause code bloat). It also copies pointer but that will be shallow copy (if pointer is pointing to some location, the copied pointer will also point to same location).

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 8
    Nope, they do a member by member copy. –  Apr 18 '11 at 08:24
  • @iammilind: "byte-by-byte copy... not good for larger arrays... causes code bloat"... clearly the "larger" precludes the only slight "code bloat" situation: arrays so small the compiler unrolls the loop as a performance optimisation. For larger arrays, the compiler will generate a loop or make a function call (to something like memcpy()), so the amount of code generated is constant regardless of array size. – Tony Delroy Apr 18 '11 at 08:45
  • @Tony, thanks for the info. I was not aware that compilers have such optimizers. – iammilind Apr 18 '11 at 09:02
  • 1
    @iammilind: You're welcome. Actually, the member by member copy that unapersson mentions is typically done by a loop calling the copy constructor for each element in the array in turn, so you can be confident of constant size even with optimisation off. The optimisation cases are loop unrolling and/or function call. Cheers. – Tony Delroy Apr 18 '11 at 09:14
  • @Tony, so that means, if we don't have any pointer members to be "deep copied", then can get away with implementing copy constructors (and `operator =`) and rely on built-in implementation ? – iammilind Apr 18 '11 at 09:44
  • @iammilind: get away "without", yes - exactly. Even for pointers, you can consider using a "smart pointer" that provides acceptable default behaviour, whether that's a shallow copy but coordinated deletion when no pointers to the object exist any more (a "shared" pointer), or some deep-copying smart pointer that copies the pointed-to content when it's copied: that way the auto-generated copy constructor, destructor etc. will do the right thing (and your code will be more easily exception-safe). boost has a nice collection of smart pointers. – Tony Delroy Apr 18 '11 at 10:20