kenics.net

Technical notes on perl, python, php, sql, cgi, c/c++, q/kdb+, unix/shell, revision control tools, data structures & algorithms, and their applications into web services and other various forms of software engineering.

C++ const volatile mutable

 
############################# 
####   const  accessor   #### 
############################# 
 
const lets you declare/define things to be constant, i.e. immutable. 
 
even though technically you can do without it, you should use const when you intend something to be not changed. not just to make things safer, but also it shows better design purpose to the reader. 
 
------------------------- 
  const int aaa = 111; 
  aaa = 222;               // compile error 
------------------------- 
 
 
you cannot assign a constant variable value into a non-constant variable. 
 
------------------------- 
  const int aaa = 123; 
  int bbb = aaa;           // this is error in C++. but not in C.  see the next section. 
------------------------- 
 
but with casting, you can over turn. (though you should be careful.) 
------------------------- 
  const int xx = 111; 
  int yy = (int) xx;       // legal 
------------------------- 
 
############################### 
###  diff between C & C++   ### 
############################### 
 
const in C means a variable you cannot change. not a constant expression. 
const in C++ means it's a constant val. 
 
e.g. 
-------------------------- 
const int num = 100; 
char arr[num];          // you can only do this in C++  // but C also lets you do this since C99 
-------------------------- 
 
 
 
 
############################ 
####   const pointer    #### 
############################ 
 
there are two kinds of const when used for a pointer. 
 
compare the below two; 
------------------------ 
int val = 123; 
const int* foo = &val;       // this means you cannot change the data content which the pointer points to. 
int* const bar = &val;       // this means you cannot change the addr the pointer holds. 
------------------------ 
 
===> for extra confusion, the first type can be written as below. 
---------------------------- 
int const* foo = &val;    // same as    const int* foo = &val; 
---------------------------- 
===> so you need to remember, if the const keyword comes before star, then cannot change the content, if const comes after star, then cannot change the addr. 
 
===> so, it's legal to write something like this; 
---------------------- 
const int* const baz;    // cannot change the content nor the addr. 
---------------------- 
 
 
 
### extra C++ vs C tricky example 
 
---------------------------- 
const int val = 123; 
int* foo = &val; 
*foo = 456;                    // compile error in C++. but in C, it compiles though the behavior is not guaranteed. 
----------------------------   // should use    const int* foo = &val;  in the 2nd line. 
 
 
 
###  versus #define 
 
#define is a constant expression definition. useful if you are using C. 
 
---------------------- 
#define SIZE (123) 
const int size = 123; 
--------------------- 
 
==>  diff here is 
 (1)you can clarify the data type "int" with const, whereas #define does not let you. 
 (2) #define is a pre-prosessor instruction which stays effective thru the whole source until nullified using #undef whereas const lets you specify the scope more flexibly. 
 (3) const lets you access an address of the variable. 
 
 
 
####################### 
####   volatile    #### 
####################### 
 
volatile qualifier tells the compiler dont optimize cos we really want this variable to have this data with actual mem allocation. because what's seemingly inefficient may have a significant meaning which the compiler cannot recognize. 
 
a few examples below; 
 
------------------------ 
int aaa = 100; 
... 
... 
int bbb = aaa; 
... 
... 
------------------------ 
 
=======> imagine bbb is used in the rest of the code, but aaa is never used, then compiler can trim the first line and make int bbb = 100; 
=======> so you might write it as   volatile int aaa = 100;   if for example, aaa's value can change which compiler cannot detect in the source code. 
 
=======> more realistic and familiar cases are in the embedded systems field; 
 
------------------------ 
int main() 

int* lcd = (int *)0x3f8a;   // suppose this is pointer to an address of some LCD panel; 
 
    *lcd = 1; 
 
    ...  
 
    *lcd = 2; 
 
    ... 
 
    *lcd = 3;                   // compiler may trim the first two, but you wanted a counter to signal other components, etc. 

------------------------ 
 
=========>  thus, write     volatile int* lcd = (int *)0x3f8a; 
 
 
 
################################## 
####   const member varibale   ###   only in C++ 
################################## 
 
const used for class member variable is no different from normal const usage. 
 
usage example; 
 
---------------------------------  // cmv.h 
class CFoo 

 public: 
  // some func, variables 
 private: 
  static const int SIZE = 123;     // declaration. yes, this is ok in modern C++. but VisualC++6.0 will make this as compile error. 
};                                 // it's just weather we agree to allow initialiation at declaration. 
 
---------------------------------  // cmv.cpp 
#include "cmv.h" 
 
const int SIZE;                    // definition. for VisualC++6.0  you do "= 123" initialization here. 
 
// member func definitions 
--------------------------------- 
 
 
=======>  what if you want to write some thing like below in VisualC++6.0 ? 
 
--------------------------------  // cmv.h 
class CFoo 

 public: 
  // some func, variables 
 private: 
   static const int SIZE; 
   int arr[SIZE]; 
}; 
--------------------------------  // cmv.cpp 
#include "cmv.h" 
 
const int SIZE = 123; 
-------------------------------- 
 
 
========>  you use what's known as "enum back" 
 
--------------------------------  // cmv.h 
class CFoo 

 public: 
  // some func, variables 
 private: 
   enum{ SIZE = 123 };            // note it's gonna be only int you can define 
   int arr[SIZE]; 
}; 
-------------------------------- 
 
 
################################## 
####   member initilization    ### 
################################## 
 
also refer to the init section of cpp_class note. 
 
------------------------------------ 
#include <iostream> 
using namespace std; 
 
class CFoo 

  public: 
  CFoo() : val(123){}               //  this is calling a constructor to an int class 
  // CFoo(){ this->val = 123;}      //  this will be an error. cannot modify a read-only const variable. 
    int get(){return this->val;} 
  private: 
     const int val;                 // you cannot initialize a value because it does not exist until instantiated. 
}; 
 
int main() 

  CFoo cf; 
  cout << cf.get() << endl;         //  123 
  return 0; 

------------------------------------- 
 
 
 
################################### 
###    const member function    ### 
################################### 
 
------------------------------------- 
class CFoo 

  public: 
    int get() const {return this->num;}  // this says get() will NOT change the member variables. 
  private: 
int num; 

------------------------------------- 
 
Also, const member function CANNOT call non-const member functions. 
(it's obvious when you think about the spec that const member func cannot change any member variables. non-const member functions can. thus calling it could mean breaking the rule.) 
 
 
###  a tricky example 
 
a const member function and another non-const member function with the same name constitute overloading functions. 
 
--------------------------- 
class CFoo 

public: 
  const int* get() const{ return foo;} 
  //  int* get(){ return const_cast<int*>( static_cast<const int*>(this)->get() ) ;} 
  // this should work but maybe not. 
  // it's forcing to call const ver get(), and remove const cast. 
 
  int* get(){ *foo = 777; return foo ;} 
  void set(int x){ *foo = x;} 
private: 
  int* foo; 
}; 
 
int main() 

  CFoo cf; 
  cf.set(123); 
 
  const int* p = cf.get(); 
 
  cout << *p << endl;            // should be 123.  but got 777. could be due to compiler 
  cout << *(cf.get()) << endl;   // 777 
 
  return 0; 

 
 
--------------------------- 
 
 
 
########################## 
####     mutable      #### 
########################## 
 
a qualifier you can cast on non-static member variable.  a mutable member variable, you can modify from a const member function. 
you can essentially achieve the same thing by const_cast. 
 
----------------------------------------------- 
class CFoo 

public: 
       void modify(int x) const { num = x;}            // compiler error 
private: 
       int num; 
}; 
----------------------------------------------- 
 
----------------------------------------------- 
class CFoo 

    public: 
       void modify(int x) const { num = x;}            // compile ok 
    private: 
       mutable int num;                                // mutable 
}; 
----------------------------------------------- 
 
###  when is this useful? 
 
one example is when you implement caching scheme invisible from the outisde of the class. 
 
 
 
 
 
(ref) 
http://stackoverflow.com/questions/6290904/const-in-c-cannot-allocate-an-array-of-constant-size-0 
http://www.geocities.jp/ky_webid/cpp/language/020.html 
http://www.geocities.jp/ky_webid/ProgrammingPlacePlus/c/037.html

  1. 2014-05-08 02:00:16 |
  2. Category : cpp
  3. Page View:

Google Ads