Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Size of an array

This question is about C++

I always thought that name of an array in C++ is only a pointer, so I thought that

int ar[10];
cout << sizeof(ar);

will give me the same as sizeof(int *). But it gives 40 - so it is real size of whole array. It also gives 40 when array size is given by variable:

int n = 10;
int ar[n]

I want to copy a class that contains an array. If it would be allocated with operator new then I should manualy copy this array within a copy constructor. But how about constant sized arrays? Does class contains only a pointer to an array, or does it contains whole array? Is simple memcpy(...) safe here?

EDIT: Another example:

int n;
cin >> n;
int ar[n];
cout << sizeof(ar);

and it prints n*4. I'm using g++ on linux.

I even tried this:

class Test {
public:
    int ar[4];
};

and

Test a, b, c;
a.ar[0] = 10;
b = a;
memcpy(&c, &a, sizeof(a));
a.ar[0] = 20;
cout << "A: " << a.ar[0] << endl;
cout << "B: " << b.ar[0] << endl;
cout << "C: " << c.ar[0] << endl;

and it gives:

A: 20
B: 10
C: 10

So array is stored as a part of a class and can be copied with memcpy. But is it safe?

like image 858
klew Avatar asked Jan 19 '26 03:01

klew


2 Answers

An array is not a pointer. The name of an array "decays" to a pointer when/if you pass it as a parameter to a function -- but sizeof is an operator built into the language, not a function, so sizeof(array) yields the actual size of the array as long as it's applied to the actual array (as opposed to the name of the array being passed as a parameter, then using sizeof() on the pointer that it decayed to when it was passed to the function.

As far as copying a class that contains an array, if it's really an array, like:

class X { 
    int x[10];
};

Then you don't need to do anything for it to be copied -- the compiler can/will generate a copy constructor that copies the contents of the array. If (and only if) you actually have a pointer, and allocate the space yourself, do you need to write a copy ctor to do a "deep copy" (i.e. allocate space in the new object, and copy the data pointed TO by the pointer). Rather than doing this, however, you should normally use an std::vector, which does all that internally so you don't have to worry about it.

like image 134
Jerry Coffin Avatar answered Jan 21 '26 18:01

Jerry Coffin


Taking these one at a time:

I want to copy a class that contains an array.

Okay, so for example:

class Foo
{
    int arr[20];
};

If it would be allocated with operator new then I should manualy copy this array within a copy constructor.

Okay, now the confusion sets in. In the above example, the array is actually part of the object. sizeof(Foo) would give you 80 if int is 4 bytes.

An alternative would be to have a pointer to an array, which is useful if the array needs to change size:

class Bar
{
    int *arr;
};

In that case, sizeof(Bar) is the size of a pointer (usually 4 or 8 bytes), and copying the object copies the pointer. This is called a "shallow copy". If you wanted a "deep copy", i.e. a copy would duplicate the array's contents and not just the object, then you need a copy constructor.

The third alternative is to use vector, as wheaties recommends:

class Bob
{
    std::vector<int> arr;
};

This internally works the same as the Bar case, and the vector can be resized, but the vector template takes care of the deep copy for you, so you don't need a copy constructor.

I'd recommend the Foo case if you need a fixed-size array, where the size is known at compile time, and the Bob case otherwise. The Bar case is pretty much just reinventing the wheel.

Is simple memcpy(...) safe here?

Safe for Foo. Safe for Bar if you want a shallow copy. Unsafe for Bob.

The moral of the story is that storing a variable in an object works just like storing it in a function block or global: if you specify an array ([N] instead of *), the size had better be determined at compile time, and you get the storage placed right there.

like image 24
Mike DeSimone Avatar answered Jan 21 '26 20:01

Mike DeSimone



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!