Aviv Cohn
Aviv Cohn

Reputation: 17193

What exactly is a const variable?

I understand const pointers. However I don't entirely understand const normal variables.

const int a

The statement above I understand because it's a primitive. So it can only mean one thing: the value of a cannot be changed.

But whag about this one?

const Car car

This could mean one of two things:

A- The value of variable car can't be changed. I.e., I can't put inside it a different Car.

B- The object itself that this variable holds cannot be changed. I.e., we can't change the state of the object that's inside this variable.

Which one of these is correct?

Upvotes: 2

Views: 181

Answers (4)

Stuart Golodetz
Stuart Golodetz

Reputation: 20616

This isn't an entirely straightforward question. Specifically, making car const makes the compiler treat all of car's non-mutable members as const. It also prevents you from calling non-const member functions on car.

What does treating a member as const mean? Well, it depends on its type. If it's a pointer, it's the pointer and not the pointee that is treated as const. Say we have the following class:

class C
{
public:
  Foo foo;
  Bar *bar;
  mutable Baz baz;

  void nc()
  {
    foo = ...;  // fine
    bar = ...;  // fine
    *bar = ...; // fine
    baz = ...;  // fine
  }

  void c() const
  {
    foo = ...;  // not fine
    bar = ...;  // not fine
    *bar = ...; // fine
    baz = ...;  // fine
  }
};

const C c;
c.foo = ...;  // not fine
c.bar = ...;  // not fine
*c.bar = ...; // fine
c.baz = ...;  // fine
c.nc();       // not fine
c.c();        // fine

If you had a const instance of C, you would be able to call const member functions on it. You (depending on access) or those const member functions would also be able to change the thing pointed to by bar and the actual object baz, but not foo or bar, since the compiler would treat foo as being of type const Foo, bar as being of type Bar *const and baz as being of type Baz.

To directly address your question, both A and B are roughly correct views of what's going on, but neither captures the true situation well enough to be an answer to the question.

In particular, A (which essentially says you can't assign to const objects) is a simplification, since it's possible (maybe unwise, but possible) to write an assignment operator that only assigns to mutable members or to pointees.

B is a simplification because it doesn't take into account the possible presence of mutable members inside your class. Depending on what you mean by 'state', it's closer to the truth, since mutable members are often used as part of the private implementation and don't represent part of the class's logical state, but it's still not really accurate.

Upvotes: 2

marcinj
marcinj

Reputation: 49986

Both are correct:

A- The value of variable car can't be changed. I.e., I can't put inside it a different Car.

you will not be able to assign to car any other Car class instances. If you are using java, then this is not the same as assigning reference to new variable, in c++ whole object is copied in this case.

B- The object itself that this variable holds cannot be changed. I.e., we can't change the state of the object that's inside this variable.

its correct because you will only be able to call const methods which are also not allowed to modify fields, unless they are marked as mutable.

Upvotes: 2

Drax
Drax

Reputation: 13278

Both.

Since The value of variable car and the state of the object that's inside this variable are the same thing.

An objects is nothing more than the aggregation of its members.

Upvotes: 2

Sneftel
Sneftel

Reputation: 41474

Both are true. Assigning a new Car to car is done by invoking Car::operator=(Car const& other), whether explicitly implemented or compiler-generated. That, in turn, assigns all of the members of car from those of other. So assignment is state-changing.

From the confusion, I wonder if you're more used to a language like C# or Java which has reference-typed object variables instead of object-typed variables. There (like with pointers in C++), assigning to a variable is different from changing its state, because the original Car stored in car would still be out there somewhere, unchanged. But with value-typed object variables, you're not really putting "a different Car inside it" -- you're changing the original Car so that it looks the same as the new Car.

Upvotes: 1

Related Questions