7

For the following code:

class A
{
public:
    const int cx = 5;
};

Here, an instance of cx will be created for every object of A. Which seems a waste to me, as cx can never be modified. Actually, I don't see any reason why compiler shouldn't enforce making a const data member static. Can anybody please explain this to me ?

Sam
  • 173
  • 1
  • 7

4 Answers4

11

A const data member does not have to be the same for all instances. You can initialize it in the constructor.

class A
{
public:
    A(int n) :cx(n) {}

    const int cx;
};

int main()
{
    A a1(10);
    A a2(100);
}
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 1
    With the caveat that you must initialize it in the initializer list. By the time you enter the body of the constructor, it's too late. i.e. this fails: `A(int n) { cx = n; }` – dgnuff Nov 03 '14 at 18:53
6

Actually, I don't see any reason why compiler shouldn't enforce making a const data member static.

Have you considered that cx might be initialized in the constructor with a value known at run-time - and varying between different instances of A?
const members make assignment to them impossible, but sometimes having a member that cannot change its initial value proves useful.

Definitely not the best example, but to illustrate the idea:

struct Multiplier
{
    const int factor;

    Multiplier(int factor) : factor(factor) {}

    int operator()( int val ) const
    {
        return val * factor;
    }
};

std::vector<int> vec{1, 2, 3};
std::vector<int> vec2;

int i;
std::cin >> i;

std::transform( std::begin(vec), std::end(vec),
                std::back_inserter(vec2), Multiplier(i) );

// vec2 contains multiples of the values of vec
Columbo
  • 60,038
  • 8
  • 155
  • 203
1

If the value is initialized with a constant, as in your example, it's probably better that it be static. But that's not always the case; it's quite frequent to have something like:

class Matrix
{
    const int myRowCount;
    const int myColumnCount;
    std::vector<double> myData;
    //  ...
public:
    Matrix( int rows, int columns )
        : myRowCount( rows )
        , myColumnCount( columns )
        , myData( rows * columns )
    {
    }
    //  ...
};

In this case, the const expresses clearly that the number of rows and columns in any given instance will not change. (On the other hand, it blocks the default assignment operator from being generated. Which may or may not be a good thing.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

There are some limitations on using non-static const member.

Let's say there's class Employee. First, although the compiler can generate a correctly-working copy constructor , it cannot generate an assignment operator. If a program creates two Employee objects e1 and e2, the statement e1 = e2 will cause a compiler diagnostic. This assignment is invalid because it implicitly attempts to change the value of the const member. Although you can have assignment operator by casting away const-ness but again that's not a good idea.

Another limitation is that it is difficult to provide a useful default constructor for this class. A default constructor is essential if you want to create, say, arrays of Employee objects. Defining a default constructor is a little bit tricky; the main thing to remember is that const non-static data members get initialized in the constructor's initialization list — and you must initialize all of them. The default constructor must set the dob field to some value, and this value cannot be subsequently altered. So the constructed array will be practically useless

ravi
  • 10,994
  • 1
  • 18
  • 36