user16038533
user16038533

Reputation:

How can I get a method to return a pointer to a const array

Consider the following code.

class SomeClass{};

class AnotherClass
{
public:
    SomeClass c1;
    SomeClass c2;
    SomeClass c3;
    const SomeClass* someClassArray[3] = { &c1, &c2, &c3 };
    
    const SomeClass** GetSomeClassArray () 
    {
      return someClassArray;
    }
};

int main ()
{
    AnotherClass anotherClass;
    const SomeClass** someClassArray = anotherClass.GetSomeClassArray ();
    
    SomeClass* someClass2 = new SomeClass;
    someClassArray[0] = someClass2; //This should not be allowed
}

I am declaring the array someClassArray as const. I am specifying the return type of GetSomeClassArray as const SomeClass** and yet, I am still allowed to modify the contents of the array later in the main function.

I also noticed that adding const specifier to the method as such: const SomeClass** GetSomeClassArray () const causes an error.

Why is this the case?

Upvotes: 0

Views: 87

Answers (2)

Loki Astari
Loki Astari

Reputation: 264381

Your interpretation of what is const is wrong.

The term const binds left (unless it is on the very left then in binds right).

// so This
const SomeClass* someClassArray[3] = { &c1, &c2, &c3 };

// Equivelent to this:
SomeClass const * someClassArray[3] = { &c1, &c2, &c3 };

So now we can read the type easier. Types are read right to left.

SomeClass const * [3]
                  ^^^ Array of
                ^     Pointer To
^^^^^^^^^^^^^^^       const SomeClass

So you have an array of pointer to "const SomeClass". So the "SomeClass" object are const but the pointers are not. If you want the array to be imutable then make the pointers also const.

SomeClass const * const [3]
                        ^^^ Array of
                ^^^^^^^     const Pointer To
^^^^^^^^^^^^^^^             const SomeClass

That being said. That's probably not the best way of declaring that.

Why not just declare an array of objects?

    const SomeClass someClassArray[3];

Also a return type of ** is loosing information on the size of the array, so that is not the greatest.

     // Updated to put const in correct place first.
     SomeClass const  *const  * GetSomeClassArray() {return someClassArray;}

     // The syntax for return an array by reference is 
     // super non intuitive. I could spend 30 minutes
     // looking up the exact syntax or we can let the
     // compiler do it for you.

     auto& GetSomeClassArray() {return someClassArray;}

or

     auto const& GetSomeClassArray() {return someClassArray;}

You want to keep the type information about the size of the array as this will help in sveral ways.


Since we are using C++ you can consider using std::array rather than a C array (or std::vector potentially).

  const std::array<SomeClass, 3> someClassArray;

Upvotes: 1

super
super

Reputation: 288

When you declare const SomeClass* p, it is *p that is const. So when you declare const SomeClass** p, it is **p that is const and not *p. If you want *p to be const, you have to put const SomeClass* const* p.

Upvotes: 0

Related Questions