Const (computer programming): Difference between revisions

Content deleted Content added
Pointers and references: Cleanup; int&const gives an error on g++
Line 51:
 
The first, which applies only to C++, is the use of <code>const_cast</code>, which allows the programmer to strip the <code>const</code> qualifier, making any object modifiable. The necessity of stripping the qualifier arises when using existing code and libraries that cannot be modified but which are not <code>const</code>-correct. For instance, consider this code:
// Prototype for a function which we cannot change but which
// we know does not modify the pointee passed in.
void LibraryFunc( int * ptr, int size );
 
void CallLibraryFunc( int const * const ptr, int const size )
<code>
{
// Prototype for a function which we cannot change but which
LibraryFunc( ptr, size ); // Error! Drops const qualifier
// we know does not modify the pointee passed in.
void LibraryFunc( int * ptr, int size );
int *const nonConstPtr = const_cast<int*>( ptr ); // Strip qualifier
 
LibraryFunc( nonConstPtr, size ); // Ok
void CallLibraryFunc( int const * const ptr, int const size )
}
{
LibraryFunc( ptr, size ); // Error! Drops const qualifier
 
int *const nonConstPtr = const_cast<int*>( ptr ); // Strip qualifier
LibraryFunc( nonConstPtr, size ); // Ok
}
</code>
 
The other loop-hole applies both to C and C++. Specifically, the languages dictate that member pointers and references are "shallow" with respect to the <code>const</code>-ness of their owners &mdash; that is, a containing object that is <code>const</code> has all <code>const</code> members except that member pointees (and referees) are still mutable. To illustrate, consider this code:
struct S
 
{
<code>
structint S val;
{int * ptr;
};
int val;
int * ptr;
void Bar( struct S const s )
};
{
 
voidint Bar(i struct S= const s )42;
s.val = i; // Error: s is const, so val is a const int
{
s.ptr = &i; // Error: s is const, so ptr is a const pointer
int i = 42;
*s.val ptr = i0; // ErrorOk: sthe isdata const,pointed soto valby becomesptr ais constalways intmutable,
s.ptr = &i; // Error: s is const, soeven ptrthough becomesthis is ausually constnot pointerdesirable
}
*s.ptr = 0; // Ok: the pointee known by s is always mutable,
// though this is usually not desirable
}
</code>
 
Although the structure <code>s</code> passed to <code>Bar()</code> is constant, which makes all of its members constant, the pointee accessible through <code>s.ptr</code> is still modifiable, though this is not generally desirable from the standpoint of <code>const</code>-correctness because <code>s</code> may solely own the pointee. For this reason, some have argued that the default for member pointers and references should be "deep" <code>const</code>-ness, which could be overridden by a <code>mutable</code> qualifier when the pointee is not owned by the container, but this strategy would create compatibility issues with existing code. Thus, for historical reasons, this loop-hole remains open in C and C++.