tdwig
tdwig

Reputation: 41

Passing array to class function C++

I have a 2D array organized as

float vertices[3][3]

In one iterative loop of my program, I see in my debugger that the the array fills up as so:

vertices[0] = {-1, -1, 1}
vertices[1] = {-1, -.5, .5}
vertices[2] = {-.5, -1, .5}

I then pass the three vertices to my triangle class.

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(*t);

The triangle constructor is coded as so:

Triangle::Triangle(float *a, float *b, float *c)
{
    memcpy(v1, a, sizeof(a));
    memcpy(v2, b, sizeof(b));
    memcpy(v3, c, sizeof(c));
}

My debugger now shows

v1 = {-1, -431602080, -431602080}
v2 = {-1, -431602080, -431602080}
v3 = {-.5, -431602080, -431602080}

Debugger also shows that a/b/c are only 1 element long? So apparently only the first element of the array is being passed?

Upvotes: 0

Views: 981

Answers (5)

Aiken Drum
Aiken Drum

Reputation: 593

Aside from the other solutions, I want to point out that your code has a memory leak:

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(*t);

When you push_back(*t), you are pushing a copy of the allocated object at *t, not a copy of the pointer t. The vector internally allocates space for another Triangle and copies the given object into it. After this code, that pointer is lost and the allocated object is orphaned/leaked.

If you mean to keep your triangles as individually-allocated objects, then triangles should be a vector<Triangle *> and the code should look like this:

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(t);

If you mean to keep triangles as a vector<Triangle>, then you want something more like this:

Triangle t(vertices[0], vertices[1], vertices[2]);
triangles.push_back(t);

Or, if your compiler/stl implementation supports vector::emplace_back(), this is even simpler:

triangles.emplace_back(vertices[0], vertices[1], vertices[2]);

Which does the construction directly into the new entry in the vector.

Upvotes: 0

Jarod42
Jarod42

Reputation: 218238

An alternative is to expected fixed size float array:

Triangle::Triangle(const float (&a)[3], const float (&b)[3], const float (&c)[3])

but passing size or using std::array<float, 3> or std::vector<float> seems simpler.

Upvotes: 0

CinCout
CinCout

Reputation: 9619

In your case, sizeof(a) will give you the size of the pointer, not the data it points to. This is because a is a float pointer!

Do this: Pass number of elements (3 in your case) as a parameter:

    Triangle::Triangle(float *a, float *b, float *c, int numElements)
    {
        memcpy(v1, a, sizeof(a) * numElements);
        memcpy(v2, b, sizeof(b) * numElements);
        memcpy(v3, c, sizeof(c) * numElements);
    }

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409442

The problem here is your use of the sizeof operator, because once an array has decayed to a pointer it looses all size information, and in the function doing e.g. sizeof(a) will only give you the size of the pointer and not what it points to.

There's an easy way to solve these problems in C++, and that is to use either std::vector or std::array instead. If you for some reason don't want to use those handy classes, then you need to pass the size to the function in some way, like for example an argument or as a template parameter.

Upvotes: 0

Dmitrii Z.
Dmitrii Z.

Reputation: 2357

sizeof(a)

is actually

sizeof (float*)

which is not 3x float, it is 1 pointer. Pass additional parameter size_t number_of_members_in_array and replace

memcpy(v1, a, sizeof(a));

with

memcpy(v1, a, sizeof(*a) * number_of_members_in_array);

Triangle::Triangle(float *a, int numA, float *b, int numB, float *c, int numC)
{
    memcpy(v1, a, sizeof(float) * numA);
    memcpy(v2, b, sizeof(float) * numB);
    memcpy(v3, c, sizeof(float) * numC);
}

Upvotes: 3

Related Questions