stream to string
#include
ostringstream out;
out << "hello";
cout << out.str();
STL vector
vectorの末尾に要素を追加するためのメソッドは、push_back()
#defineマクロ
これはCのプリプロセッサの機能だがトークンから文字列を生成することができる。たとえば、変数名xを文字列として表示したい時は #引数名 と書けばよい。
#include
#define STRINGIZE(x) #x
int main() {
int y = 0;
printf("%s:%d\n", STRINGIZE(y), y);
}
この操作を造語でstringizeという。まあ「文字列化」みたいな感じだ。
これを
#define STRINGSIZE(x) "x"
としてしまうと、引数に関わらず単純に文字列"x"に変換されてしまい、STRINGSIZE(y)でも"x"が返されてしまう。
hash_map
hash_map::insert()の1つはこんな風に定義されている。
pair<iterator,bool> insert(const value_type& __obj)
{ return _M_ht.insert_unique(__obj); }
つまり、hash_map::insert()を使うには引数にconst value_type&型のものを渡せばいい。
value_typeは、
typedef typename _Ht::value_type value_type;
として宣言されている。typenameはC++のキーワードで、続くトークンは型だと明示する。つまり、_Ht::value_typeは型である。_Htはどこで定義されているかといえば、その寸前で、
private:
typedef hashtable<pair<const _Key,_Tp>,_Key,_HashFcn,
_Select1st<pair<const _Key,_Tp> >,_EqualKey,_Alloc> _Ht;
となっている。_Htは平たく言えばHashtableを指している。このhashtable<...>テンプレートは、stl_hashtable.hで定義されていて、_Ht::value_typeは、このヘッダーで、
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable {
public:
typedef _Val value_type;
}
と定義されているので、hash_mapの場合は、上のhashtableのtypedefが使われるから、
typedef pair<const _key,_Tp> value_type;
となる。
binary_function
functionオブジェクトはoperator()が定義されたオブジェクトである。
binary functionオブジェクトは2つの引数を取るfunctionオブジェクトである。
Unsignedなリテラル
0x80がUnsigned intだと主張するためにはこう書く。
0x80u
サフィックスuをつければよい。
コンストラクタから同じクラスの別のコンストラクタを呼び出す
文法上エラーにはなりませんが、うまく動きません。別のコンストラクタにせず、通常のメソッド(たとえばClassName::Initialize())にしてコンストラクタから呼び出します。
参考:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3
constの意味
- 変数がconstで定義された場合、その値を変更することができない。
- 関数の引数がconstで定義された場合、その値を変更することはできない。
- メンバ関数がconstで宣言された場合、オブジェクトの状態を変更することがない(?)
const char * a;
・まず変数aに着目する。
・aの手前にある'*'に着目する。 * ← a、つまりvariable a is a pointer.
・'*'の前のcharに着目する。char ← * ← a、つまり、variable a is a pointer to char.
・最後に残ったconstに着目。const ← char ← * ← a、つまり、variable a is a pointer to char, which is const.
これは、「変数aはポインタで、それはcharを指す。そのcharは変更不可(const)である」と読めばよい。言い換えると、charは変更できないが、それを指しているポインタが変更できない(=constだ)とは言っていない。
a : (char*型) : ○変更可
*a : (char型) : ×変更不可
const char * a;
a = &b; // OK
*a = 'x' // NG
char * const a;
これも同じように変数名から読み始めればよい。
・変数aは、constである。つまり変更できない。variable a is const.
・* ← const ← a、variable a is const and it is a pointer.
・char ← * ← const ← a、variable a is const and it is a pointer to char
つまり、「変数aは変更不可なポインタで、それはcharを指す」となる。日本語的に言い換えると、「変更不可の変数aは、charポインタである」となる。
今度は、ポインタ変数a自体にconstが適用されるので、aを変更することはできないが、指している先の中身は変更できる。
char * const a;
a = &b; // NG
*a = 'x' // OK
char const * a
こんな宣言も可能だ。同じ方法で読んでみると、
・a is a variable. The variable is a pointer.
・The variable(a pointer variable) is const, and it point char.
つまり、char const * aも、const char * aも同じ意味になる。
const char * const a;
これは、ポインタ自体もポインタが指す先の中身も変更できないようにする宣言。「変数aは変更不可であり、ポインタである。それはcharを指す。そのcharは変更不可である。
constメソッド
メンバ関数にconstを使うこともできる。
class A {
void Method1(int n) const {
x_ = n; // NG
}
private:
int x_;
};
メンバ関数宣言の最後にconstをつける。この場合、メンバ変数を書き換えることができない(mutableでない)ことを示す。具体的には、*this(thisが指すインスタンス)を変更することができない。
メンバ関数宣言の先頭にconstをつけないのは、戻り値を修飾するconstと区別がつかなくなってしまうからだろう。
constなメンバ関数を呼び出した時に、内部的に状態を変更をしたいが、それが外の世界にとって挙動に変化を与えない場合、その内部変数にmutableキーワードをつけることで、constメンバ関数のまま、この振る舞いを実現できる。mutableキーワードがつけられたメンバ変数は、constメンバ関数から変更が許可される。
練習
const string& s;
const stringへのreferenceであるs。sは書き換えられない。
const string* s;
const stringへのポインタs。sは書き換えられるが、*sは変更できない。
リスト操作
リストの要素を先頭から6個削除する。一応vectorの場合を例にする。
vec.erase(vec.begin(), vec.begin() + 6);
C++でキューを使う
http://www.gaku.net/journal/i170.html
文字列クラス stringクラス
NULL-terminateでない文字列を代入する。
→string.append()を使えばよい。
string s;
char* p;
int len;
s.append(p, len);
文字列の長さ
string.length()
またはstring.size()
文字列に文字列が含まれているかどうか?
if (string::npos != string.find("@", 3)) {
...
}
文字の削除
s.erase(0,1)
0文字目から1文字削除。