karadoc
karadoc

Reputation: 2721

Preventing a const member function from changing a member array

Apparently, a const member function is still allowed to change data that the class member are pointing to. Here's an example of what I mean:

class MyClass
{
public:
  MyClass();
  int getSomething() const;
private:
  int* data;
};

// ... data = new int[10];, or whatever

int MyClass::getSomething() const
{
  data[4] = 3; // this is allowed, even those the function is const
  return data[4];
}

I'd prefer if this was not allowed. How should I define "data" so that "getSomething() const" isn't allowed to change it? (but so that non-const functions are allowed to change it.) Is there some kind of "best practice" for this? Perhaps std::vector?

Upvotes: 5

Views: 1762

Answers (3)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361802

In a const member function, the type of data changes from int* to int *const:

int * const data;

which means, it's the pointer which is const in the const member function, not the data itself the pointer points to. So you cannot do the following:

data = new int[100]; //error 

as it's attempting to change the pointer itself which is const, hence disallowed, but the following is allowed:

data[0] = 100; //ok

Because changing the content doesn't change the pointer. data points to same memory location.

If you use std::vector<int>, then you can achieve what you want. In fact, vector solves this problem, along with the memory management issues, therefor use it:

class MyClass
{
public:
  MyClass();
  int getSomething() const;
private:
  std::vector<int> data;
};

MyClass::MyClass() : data(10) {}  //vector of size 10

int MyClass::getSomething() const
{
  data[4] = 3; // compilation error - this is what you wanted.
  return data[4];
}

Avoid non-RAII design as much as you can. RAII is superior solution to memory management issues. Here, with it, you achieve what you want. Read this:

Upvotes: 7

Luchian Grigore
Luchian Grigore

Reputation: 258678

The reason you should use std::vector is actually because you want to store a collection of ints, and not an int pointer, so why not use it?

It would also solve your const'ness issue.

Here's how it works: declaring a method const will make all class members const. In your case, that means that in the method scope, your member data will become a constant pointer to an int. That means you can change the int (also meaning array members) as long as data points to the same location. Using std::vector, data would become a const std::vector, on which you could only call const functions. So yes, you should use std::vector.

Upvotes: 4

K-ballo
K-ballo

Reputation: 81409

There is no way to do what you want. Your const member function can't change the value of data (the address it points to), but there is nothing about not changing the contents it points to as you have already noticed. Using a std::vector would help, since within a const member function you would actually have a const vector, not being able to call any of its mutable functions.

Upvotes: 4

Related Questions