C++ Const Usage Explanation

C++ Const Usage Explanation

Read this: https://isocpp.org/wiki/faq/const-correctness

The final const means that the function Method3 does not modify the non mutable members of its class.

const int* const means a constant pointer to a constant int: i.e. a pointer that cannot be changed, to an int that cannot be changed: the only difference between this and const int& is that it can be null

const int* const& means a reference to a constant pointer to a constant int. Usually pointers are not passed by reference; const int* & makes more sense because it would mean that the pointer could be changed during the method call, which would be the only reason I can see to pass a pointer by reference, const int* const& is to all intents and purposes the same as const int* const except that it is probably less efficient as pointers are plain old data (POD) types and these should, in general be passed by value.

how const keyword works in c

In general const is 100% compiler. When you declare something const, the compiler places restrictions on what it will let you write. It won't let you assign to const scalar, assign through a const reference or or pointer, or invoke a non-const function of const object.

There is no guarantee that the compiler will arrange any sort of runtime protection.

Deep Analysis of Const Qualifier in C

The keyword const indicates a variable that is read-only (i.e., cannot be changed at run-time). It does not indicate a compile-time constant. Therefore, all of the usual attributes of variables apply; specifically, it is allocated addressable storage space.

Unlike with #define, your constant is not necessarily inlined by the compiler. Rather, the compiler will create a symbol corresponding to your const declaration in the object file so that it can be accessed from other code files—remember that const objects have external linkage by default in C (although some compilers will still inline the constant value within the file where it is defined).

The reason the code snippet that you posted "works" is because the unary operator & can be applied to any lvalue, which includes a const object. Though the behavior here is undefined, I suspect that your compiler is detecting this usage and ensuring that your const declaration is given address space, and therefore not inlining it, even within the file it is declared.

EDIT: Also see: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Let's look at what is meant when const
is used. It's really quite simple:
const means that something is not
modifiable, so a data object that is
declared with const as a part of its
type specification must not be
assigned to in any way during the run
of a program. It is very likely that
the definition of the object will
contain an initializer (otherwise,
since you can't assign to it, how
would it ever get a value?), but this
is not always the case. For example,
if you were accessing a hardware port
at a fixed memory address and promised
only to read from it, then it would be
declared to be const but not
initialized.

Taking the address of a
data object of a type which isn't
const and putting it into a pointer to
the const-qualified version of the
same type is both safe and explicitly
permitted; you will be able to use the
pointer to inspect the object, but not
modify it. Putting the address of a
const type into a pointer to the
unqualified type is much more
dangerous and consequently prohibited
(although you can get around this by
using a cast). For example...

C++ const keyword explanation

void myfunc(const char x);

This means that the parameter x is a char whose value cannot be changed inside the function. For example:

void myfunc(const char x)
{
char y = x; // OK
x = y; // failure - x is `const`
}

For the last one:

int myfunc() const;

This is illegal unless it's inside a class declaration - const member functions prevent modification of any class member - const nonmember functions cannot be used. in this case the definition would be something like:

int myclass::myfunc() const
{
// do stuff that leaves members unchanged
}

If you have specific class members that need to be modifiable in const member functions, you can declare them mutable. An example would be a member lock_guard that makes the class's const and non-const member functions threadsafe, but must change during its own internal operation.

C++ what is the point of const keyword?

Non-exhaustive list of reasons:

  1. Software Engineering (SWE). SWE is not just programming, but programming with other people and over time.

    const allows to explicitly express an invariant, which lets you and others reason about the code. As the program becomes bigger, these invariants cannot be just memorized. That's why encoding them in the programming language helps.

  2. Optimization opportunities.

    With the knowledge that certain values will not change, the compiler can make optimizations that would not be possible otherwise. To take this to the max, constexpr means that a value will be known at compile time, not just at run-time. This becomes even more important in potentially multi-threading contexts.

    Example:
    What kind of optimization does const offer in C/C++?

    I leave out whole program analysis which would require a much longer answer and almost certainly is not applicable to generic C++ programs. But whole-program-analysis will allow reasoning of the analyzer or compiler about constness of variables as they get passed between functions, translation units and libraries.

Using const keyword in c

This declaration

static char const *const delimit_method_string[] =
{
"none", "prepend", "separate", NULL
};

declares an array with the name delimit_method_string of pointers to string literals.

In C opposite to C++ string literals have types of non-constant character arrays. Nevertheless you may not change a string literal. Any attempt to change a string literal results in undefined behavior. So it is better to declare pointers to string literals the following way as for example

const char *s = "Hello";

So you could declare the above array like

static char const * delimit_method_string[] =
{
"none", "prepend", "separate", NULL
};

But the programmer who declared this array also wanted to declare at as a constant array. That is he wanted that its elements can not be changed.

For the declaration above you can write for example

delimit_method_string[0] = "all";

To prevent such a changing elements of the array must be constant. To do this you need to write

static char const * const delimit_method_string[] =
{
"none", "prepend", "separate", NULL
};

Now the elements of the array that have the pointer type const char * are constant due to the second qualifier const.

Tom make it more clear consider the following declarations.

char *p;

This declaration declares a non-constant pointer to a non-constant object of the type char.

const char *p;

This declaration declares a non-constant pointer to a constant object of the type char.

const char * const p;

This declaration declares a constant pointer to a constant object of the type char.

The last declaration may be rewritten like

const char ( * const p );

As for this your declaraion

char const const *ptr = &a;

then on of the two qualifiers const is redundant because the both refer to the type specifier char.

Const correctness in C vs C++

In addition to the differences you cite, and the library differences that
Steve Jessop mentions,

char* p1;
char const* const* p2 = &p1;

is legal in C++, but not in C. Historically, this is because C
originally allowed:

char* p1;
char const** p2 = &p1;

Shortly before the standard was adopted, someone realized that this
punched a hole in const safety (since *p2 can now be assigned a
char const*, which results in p1 being assigned a char const*); with
no real time to analyse the problem in depth, the C committee banned any
additional const other than top level const. (I.e. &p1 can be
assigned to a char ** or a char **const, but not to a char const**
nor a char const* const*.) The C++ committee did the further
analysis, realized that the problem was only present when a const
level was followed by a non-const level, and worked out the necessary
wording. (See §4.4/4 in the standard.)

How many and which are the uses of const in C++?

Trying to collect some uses:

Binding some temporary to reference-to-const, to lengthen its lifetime. The reference can be a base - and the destructor of it doesn't need to be virtual - the right destructor is still called:

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

Explanation, using code:

struct ScopeGuard { 
~ScopeGuard() { } // not virtual
};

template<typename T> struct Derived : ScopeGuard {
T t;
Derived(T t):t(t) { }
~Derived() {
t(); // call function
}
};

template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }

This trick is used in Alexandrescu's ScopeGuard utility class. Once the temporary goes out of scope, the destructor of Derived is called correctly. The above code misses some small details, but that's the big deal with it.


Use const to tell others methods won't change the logical state of this object.

struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};

Use const for copy-on-write classes, to make the compiler help you to decide when and when not you need to copy.

struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};

Explanation: You might want to share data when you copy something as long as the data of the originally and the copie'd object remain the same. Once one of the object changes data, you however need now two versions: One for the original, and one for the copy. That is, you copy on a write to either object, so that they now both have their own version.

Using code:

int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}

The above snippet prints the same address on my GCC, because the used C++ library implements a copy-on-write std::string. Both strings, even though they are distinct objects, share the same memory for their string data. Making b non-const will prefer the non-const version of the operator[] and GCC will create a copy of the backing memory buffer, because we could change it and it must not affect the data of a!

int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}

For the copy-constructor to make copies from const objects and temporaries:

struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};

For making constants that trivially can't change

double const PI = 3.1415;

For passing arbitrary objects by reference instead of by value - to prevent possibly expensive or impossible by-value passing

void PrintIt(Object const& obj) {
// ...
}


Related Topics



Leave a reply



Submit