Problems with const

As we said before, const isn't magic. It doesn't make your code 100% secure and protected. Knowing and understanding the rules related with const parameters and const member function will help prevent mistakes. However, failing to understand the rules and behaviors of const can lead to bugs.

The biggest problem with const in C++ is a misunderstanding of bitwise const versus logical const. This means that the compiler will try to ensure that the bits and bytes will not change through that specific variable. This doesn't mean that those bits won't change through another variable, and it doesn't mean that the data you may care about won't change. Consider the following code:

//Example of modifying const bits through different variables. 
int i = 0;
const int& ci = i;

ci = 10; //ERROR: can't modify the bits through const variable
i = 10; //OK. i is not const

std::cout << ci << std::endl;//Prints 10

In the preceding example, i is not const, but ci is a reference to a const int. Both i and ci are addressing the same bits. Since ci is marked const, we cannot change the value through that variable. However, i is not const, so we are free to modify the value. The fact that we can have a multiple const and non-const variables pointing to the same address has consequences for const member functions:

class Simple 
{
public:
Simple(void);
int GetData(void) const;
private:
int m_data;
Simple* m_this;
};
Simple::Simple(void):m_data(0), m_this(this)
{
}
int Simple::GetData(void) const
{
m_this->m_data = 10;
return m_data;
}

int main(void)
{
const Simple s;
std::cout << s.GetData() << std::endl;
return 0;
}

In the preceding code, we have given the Simple class a pointer to itself. This pointer can be used to modify its own data in a const member function. Remember, in a const member function, the this pointer is marked const, so data can't be changed through that variable. However, as in this case, the data can still be changed through another variable. Even if we didn't use another variable, the use of const_cast could also allow us to change the data:

int Simple::GetData(void) const 
{
const_cast<Simple*>(this)->m_data = 10;
m_data;
}

It is very important to understand that you should never write code like this. It is undefined behavior to try to modify a const variable with const_cast or using a non-const pointer to a const object. The original data could be placed in read-only memory, and code like this could cause the program to crash. It is also possible that the compiler could optimize away multiple reads to memory that shouldn't change. Therefore, the old value may be used for any future calculations. Casting away const with const_cast is meant for backwards compatibility with old C++ libraries. It should NEVER be used to modify const values. If there is a piece of data that needs to be modified even when the class is const, use the mutable keyword.

Even when avoiding undefined behavior, bitwise constness can get us into trouble with const member variables. Consider a simple class that will contain some dynamic memory. Since it contains dynamic memory and pointers, we should add a copy constructor, destructor, and other things to prevent memory leaks and memory corruption, but we will omit those for now since they aren't important for our discussion on const:

class LeakyArray 
{
public:
LeakyArray(int size)
{
m_array = new int[size];
}
void SetValue(int index, int value)
{
m_array[index] = value;
}
int GetValue(int index) const
{
//function is const so we can't do this
//m_array = 0;

//but we can do this!!!!!!!
m_array[index] = 0;

return m_array[index];

}
private:
int* m_array;
};

As you can see, bitwise const only prevents us from modifying the actual bits inside the class. This means we can't point m_array to a new location. However, it doesn't prevent us from modifying data in the array. There is nothing preventing GetValue from modifying the array in the const function, because the array data isn't part of the class, only the pointer is. Most users aren't concerned about where the data is located, but they would expect a const array to remain unchanged.

As you can see, being const, correct is certainly not a guarantee that the data will never be modified. If you are diligent about using const, as well as understand and avoid the problems that can arise, the benefits are worth it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.249.252