0

I want to pass a reference to an array from one object GameModel to another PersonModel, store reference and then work with this array inside PersonModel just like inside GameModel, but...

I have a terrible misunderstanding of passing an array process: In the class PersonModel I want to pass an array by reference in a constructor (see code block below). But the marked line throws the compile error

    PersonModel::PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel ) { 
        this->path = path; //<------ ERROR here:
        //PersonModel.cpp:14:22: error: incompatible types in assignment of 'int (*)[30]' to 'int [31][30]'

        this->permissionLevel = permissionLevel;
    }

Here is the header file PersonModel.h

#ifndef PERSON_MODEL
#define PERSON_MODEL

#include "data/FieldSize.h"

namespace game{
    class IntPosition;
    class MotionDirection;

    class PersonModel {
        protected:
        int path[FieldSize::HEIGHT][FieldSize::WIDTH];
        int permissionLevel;

        public:
        PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
        void setMotionDirection ( MotionDirection* md);
        void step(long time);
        void reset(long time);
    };
}

#endif 

As I see now, I can change the int path[FieldSize::HEIGHT][FieldSize::WIDTH]; declaration to int (*path)[FieldSize::WIDTH]; but it is much more confusing.

Help me understand this topic: what is the proper way to store the passed reference to an array to work with it later, like with usual 2D array.

UPDATE:

This array is a map of game field tiles properties represented by bit-masks, so it is read-only actually. All the incapsulated objects of GameModel class should read this array, but I definitely don't want to duplicate it or add some extra functionality.

There are no frameworks just bare Android-NDK.

4
  • Looks like you have to declare the path (the member of the class) to be a reference (well, pointer), instead of an array. Commented Oct 14, 2012 at 18:50
  • 1
    Array in C++ is rather a low-level, legacy C construct, and while it has its place in C++, you should at least consider using C++ data structures, such as those in STL, like std::vector, or those provided by some framework you are using (like QList of Qt). Commented Oct 14, 2012 at 18:54
  • anton-boritskiy: no. Like int (*path)[WIDTH]; and save the height somewhere. Commented Oct 14, 2012 at 19:30
  • I'd rather stick to Roddy's solution. Commented Oct 14, 2012 at 19:35

6 Answers 6

3

I think you've fallen into the classic trap of believing someone who's told you that "arrays and pointers are the same in C".

The first thing I'd do would be to define a type for the array:

typedef int PathArray[FieldSize::HEIGHT][FieldSize::WIDTH];

You then don't need to worry about confusions between reference to array of ints vs array of references to ints.

Your PersonModel then contains a reference to one of these.

PathArray &path;

and, because its a reference it must be initialised in the constructors initialization list rather than in the constructor body.

 PersonModel::PersonModel( PathArray &aPath, int aPermissionLevel ) :
   path(aPath),
   permissionLevel(aPermissionLevel)
 {
 }

Of course, holding references like this is a little scary so you might want to consider using a boost::shared_ptr or something similar instead to make the lifetime management more robust.

Sign up to request clarification or add additional context in comments.

5 Comments

Making the member reference const would help to clarify that the array is read-only inside the class.
If the GameModel contains all the PersonModel instances, then using a reference is likely reasonable and not scary at all. In that case, a shared_ptr would be unnecessary. Of course the object lifetime of the PersonModels instances would have to be strict.
@chradcliffe - yes, both valid points . I'm always a bit wary when I see classes holding 'bare' references, but that's probably just me...
is it possible to return such array from a function using return construct like this PathArray getTabletPath(); or something similar to call later like 'PathArray path = getTabletPath()' ?
@AntonBoritskiy - Yes, perfectly possible. You could also return a reference to one (but beware returning references to variables that go out of scope!!) PathArray & getPA() { PathArray p; return p; //death! };
2
  1. You cannot assign arrays as you do with value types in C++
  2. int path[x][y] resolves to the type int (*)[y]

Possible solutions are:

  1. Using memcpy/copy
  2. Using std::array

2 Comments

I would recommend against recommending memcpy when you have std::copy but it's not enough for a downvote.
Well, and I would recommend std::array. :D
0

You can't assign to an array like that. However you can use the fact that an array is a contiguous memory area, even when having an array of arrays, and use e.g. memcpy to copy the array:

memcpy(this->path, path, FieldSize::HEIGHT * FieldSize::WIDTH * sizeof(int));

2 Comments

thanks, but my idea was to use only one instance of this array
Why memcpy when you can std::copy?
0

You would have to pass a pointer to the 2d-array as you cannot pass the array as you have stated in the code snippet. I would suggest using the STL array type. Admittedly std::array is C++ '11 standard and therefore old compiler may not support it. You can also use vector which has been around longer.

vector<vector<int>>path;

You will have to resize the 2d-vector in the constructor. Indexing would look a bit funny:

path[1].[1] ....

With vectors, you can then pass it by reference.

Comments

0

the name of the array is a pointer on first element so, you can try

PersonModel( int (*path)[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );

Comments

-3

In C++ '=' implemented for primitive types like int and double but not for array(array is not a primitive type), so you should never use '=' to assign an array to new array, instead you should use something as memcpy to copy array. memcpy copy a memory over another memory, so you can use it to copy an array over another array:

// memcpy( dst, src, size );
memcpy( this->path, path, FieldSize::HEIGHT * FieldSize * WEIGHT * sizeof(int) );

2 Comments

but it would make a copy and not a reference.. My idea was to use only one instance of this array.
It has nothing to do with primitive types, arrays are not assignable by design.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.