C++に関する基本的な質問がいくつかあります。文字列を返そうとする次のコードについて考えてみます。
const std::string&
NumberHolder::getValueString() {
char valueCharArray[100];
sprintf_s(valueCharArray,"%f",_value);
std::string valueString(valueCharArray);
return valueString;
}
_valueというクラスメンバーの値を持つ文字列を返そうとしています。ただし、ローカル変数へのポインタを戻そうとしているという警告が表示されます。もちろんこれは悪いことです。この時点でC++を十分に理解している場合、これは、誰かがC++を使おうとするまでに、渡したポインターに既にdeleteが呼び出されていることを意味します。だから私は変更します:
const std::string&
NumberHolder::getValueString() {
char valueCharArray[100];
sprintf_s(valueCharArray,"%f",_value);
std::string valueString = new std::string(valueCharArray);
return (*valueString);
}
これにより、この関数の外部で存続するポインタがスタックに作成されます。ただし、ここで2つの問題があります:1)とにかくコンパイルされず、理由がわかりません(error = 'std :: string *'から 'std :: basic_string <_Elem、_Traits、_Ax>に変換できません')および2)これは、この人の削除を呼び出すために他の誰かに依存しているため、潜在的なメモリリークのようです。ここではどのパターンを使用する必要がありますか?
_std::string
_をヒープに割り当てることで、そのポイントを打ち負かしています。
次のような値で返すだけです。
_std::string NumberHolder::getValueString()
{
char valueCharArray[100];
sprintf_s(valueCharArray,"%f",_value);
return std::string(valueCharArray);
}
_
最近のほぼすべてのコンパイラは、returnステートメントで 戻り値の最適化(RVO) を実行するため、コピーを作成しないでください。次のことを考慮してください。
_NumberHolder holder;
// ...
std::string returnedString = holder.getValueString();
_
RVOを使用すると、コンパイラーは上記のNumberHolder::getValueString()
の実装のコードを生成し、_std::string
_がreturnedString
の場所に構築されるため、コピーは必要ありません。
ローカル文字列のコピーではなく、ローカル文字列に参照を返すため、この警告が表示されます。関数が戻ると、ローカル文字列は破棄され、返された参照は無効になります。したがって、参照ではなく値で文字列を返す必要があります。
std::string NumberHolder::getValueString()
一時変数を返すが、それをconst参照にバインドする場合、最初の試行は正しいです。
const std::string NumberHolder::getValueString(){}
const std::string& val = NumberHolder::getValueString();
const 。しかし、他の誰かが削除するかどうかによっては、2回目の試みは危険です。
std::string *valueString = new std::string(valueCharArray);
new
からの結果を保持するためのポインター変数を作成する必要があります。これは、ポインターを返すためです。ただし、理想的な解決策は、実際には値で返すことです。
std::string NumberHolder::getValueString() {
...
return std::string(valueCharArray);
}