[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.10.2 一時オブジェクトは意外に早く消滅する

一時オブジェクトの一部に対してポインタや参照を使うのは危険である。 コンパイラは読者が予想している前にオブジェクトを消してしまうことが良くあり、 その場合、ゴミを指すポインタが残る。 この問題が最も良く現れるのは、文字列クラスのような クラス、とりわけ char * あるいは const char * 型への変換関数を 定義しているクラスにおいてである。 これは、C++ 規格の string クラスがメンバ関数 c_str を 呼び出すよう要求している理由の一つである。 だが、何か内部構造へのポインタを返すクラスは何であれ、潜在的に この問題が発生する可能性がある。

例えば、あるプログラムで、 string オブジェクトを返す 関数 strfunc を使っていて、もう一つ別の関数 charfuncchar へのポインタに対して操作を行なうとする。

 
string strfunc ();
void charfunc (const char *);

void 
f ()
{
  const char *p = strfunc().c_str();
  ...
  charfunc (p);
  ...
  charfunc (p);
}

この場合、c_str メンバ関数が返す C の文字列へのポインタを セーブしておいて、c_str を毎回呼び出すよりも、そのセーブして おいたポインタを使うほうが妥当と思える。だが、strfunc の呼出し により作られる一時的な文字列は、p が初期化された後で破壊され、 その時点で p はフリーされたメモリ領域を指したままになっている。

こういうコードは、何か他のコンパイラの場合には問題なく動作する可能性がある。 特に、一時変数を普通のローカル変数と一緒に破壊する、 古びた cfrontベースのコンパイラでその可能性がある。 だが、GNU C++ の動作は規格に適合しているので、プログラムが 一時オブジェクトの遅延破壊に依存しているなら、それは移植性がない。

このようなコードを安全に書くには、一時変数に名前を与えて、 その名前のスコープの最後まで存在し続けるよう強制することである。 例えば、以下のように書くと良い。

 
string& tmp = strfunc ();
charfunc (tmp.c_str ());

This document was generated using texi2html 1.78.