c++の小技

Last-modified: 2011-02-03 (木) 06:25:44

前置き

説明で"hoge"とか"aho"とか使ってますが,意味はわかりますか?
googleさんで調べたところ
「日本の情報処理技術者が替え玉記号のように利用することが多い文字列。この文字は情報処理の世界ではメタ構文変数と呼ばれる.つまり"hoge"と書いてあったら「必要な文字に置き換えて使ってください」という意味なる」だそうです.
これでわかりますか?わからなかったらM2を見かけたときに聞いてください.きっとsuwakoさんが答えてくれますよ.
 
ここでは,C++の要素で基本となるような小技を紹介していくページにしたいと思います.大技になりそうなのはSTLのページや新しいページを作って誰かがまとめてくれることを切に願う.

  • List
    • const
    • 参照渡し
    • 名前空間

プログラムチェック環境 

sygwin : g++ ( ver.4.3.4)[VC++ではチェックはやってません]

const

参照 http://exlight.net/devel/cpp/cv-qualifier.html
const についてメモ書き程度だが忘れない内に書きたいことがあるので
みなさんよく知っていると思いますがこれは変数を定数化する修飾子(qualifier)ですね.
どうやらもう一つの修飾子"volatile"と合わせて"cv-qualifier"と呼ばれるそうです.

簡単な使い方

const double ConstantValue1(500);
const double ConstantValue2 = 500;

なんて使うと思います.基本ですね.

  • 注意点
    ポインタがあるときのconstの取り扱い
      const char * s1; const char へのポインタ -> ポインタがconst
      char const * s2; 同上
      char * const s3; 変数 s3がconst -> ポインタが指している先がconst
    
    実際の挙動は次のようになる.
      const char * s1; //const char へのポインタ
      char const * s2; //同上
      char * const s3; //変数 s3がconst
    
      char* str("hogehoge");
    
      s1 = str;// OK
      s1[0] = 'z'; // error
    
      s3 = str;//error
      s3[0] = 'z'; // OK
    
      const char* const s4;
      s4[0] = 'z'; //error
      s4 = str; //error
    
    
  • メンバ関数での使い方
    ここではメンバ関数での使い方を簡単に説明します.実際に色々試して挙動を確認してみてください.
      double func(引数)const{処理}//赤い部分のconst
    ここでのconstの意味はその関数内でメンバ変数が変更される演算をしてたらコンパイルエラーを吐き出してくれる.ただし"static"メンバ変数に関しては変更可能になっている.もちろん"struct"だけではなく"class"でも有効なのでどんどん使っていこう.
     struct Hoge{
      int x;
      static sx;
    
      Hoge(const double a): x(a){} // コンストラクタ
    
     int add1( const int a, const int b)const{
       return a+b;
      }//OK
    
      int add2( const int a, const int b)const{
        x  += 1;//error
        sx += 1+//OK
        return a+b;
      }
    
     };
     double Hoge::sx(100.);//初期化
    

 

参照渡し

参照渡しはc言語で言うところの関数呼び出しでポインタを渡すことに近い(ポインタとは別物).呼び出し元の関数の変数が呼び出した関数で参照されて使われるのですが,よくわからなければ,呼び出し関数で呼び出し元の関数の変数が使えるようになったとイメージしてください.

やり方 : 関数の引数に & をつける.
利点 : ポインタを使用しないので理解が簡単.

e.g.)

 void func(int& i){ // 引数のところに "&"をつけるだけ
  i += 1;
 }

int main(){
 int i=0;

 std::cout << i << std::endl;// 標準出力に 0 が出る.

 func(i);//こちらは普段通りでOK.関数内で変更された内容が反映される.

 std::cout << i << std::endl;// 標準出力に 1 が出る.
}
  • const参照
    ちょっとした小技でプログラムを少しだけ早くする方法.常に絶対に早くなるわけではなく使用しない方が早いときもある.
     
    やり方 : 参照渡しに const をつけるだけ.
    e.g.)
    void func( const std::vector& i){ /*処理*/}
    元々の標準の型(int, double, ...)などは元々最適化されているらしいく付けない方がよい.

名前空間

参照 : http://www.geocities.jp/ky_webid/cpp/language/018.html
名前空間とは namespace のことで,プログラムの一部を特定の名前を使ってグループ化できる.

利点:

  • 名前空間名が違えば,変数,関数に同じ名前が付けることができる.
  • 変数,関数をグループで管理できる.
    namespace hoge{
     void func();//宣言
     void aho(){//定義のみの場合
       func();//同名前空間ならそのまま呼び出せる.
     }
    }
    void hoge::func(){/* 処理 */}//宣言と定義を別に書く際はこんな感じになる.
    
    int main(){
     hoge::func();// :: で名前空間 hoge の func()を呼び出す.
                  //  :: はスコープ解決演算子というそうです.
    }
    

 
名前空間に関する操作を以下に記述します.

  • using宣言
    名前の完全記述をusing指定することにより,以降の名前を直接使用できる.
     using std::cout;
     cout << "hoge"<< std::endl;
     // cout はusing宣言しているのでOK,endl はしてないので全て記述.
    
  • using ディレクティブ 名前空間の利点がなくなるので使用しないこと
    名前空間をusingで指定すること.これをすると記述したファイル内ではその名前空間の変数,関数が名前空間なしで使用できるようになる.
    よく入門レベルのC++の記述で書かれることが多いが,名前空間の利点が損なわれるので特別なことがない限り使用しないようにしましょう.
     using namespace std;
     cout << "hoge" << endl;// stdをusing指定しているのでOK.
    
  • 名前空間の階層化
    名前空間の中に名前空間を作り階層化を行います.
    namespace hoge{
     namespace foo{
      void func(){/* 処理*/};
     }
    }
    main(){
     hoge::foo::func();
    }
    
    
  • 名前空間のエイリアス
    名前空間を別の名前空間に置き換えることができます.よく使う多階層な名前空間を別の名前に使用し記述の量を減らすのに便利です.名前を置き換え短縮するだけなのでしっかり名前を付ければ混乱が起きず便利です.
    namespace foo = hoge::aho::foo;
    
    main(){
     ublas::vector<double>
    
     hoge::aho::foo::func();//本来ならこれを記述する.
     foo::func();           //エイアリアスしているのでこれだけで済む.
    }
    
    これらは記述を置き換えるのでヘッダーファイルでは余り使わない方がいい(usingディレクティブは論外).