8

グローバルなクラスがあるとします(たとえば、アプリのランタイムで利用可能)

class MyClass {
  protected:
    std::string m_Value;
  public:
    MyClass () : m_Value("hello") {}
    std::string value() { return m_Value; }      
};

MyClass v1;

最初のフォームを使用すると、私が行うときに奇妙な動作をします

printf("value: %s\n", v1.value().c_str());

printfが使用する前に、文字列がメモリから消えたように見えます。値を出力する場合もあります。それ以外の場合は、クラッシュするか、何も出力しません。

私が最初にそのように文字列をコピーした場合

   std::string copiedString = v1.value();
   printf("value: %s\n", copiedString.c_str());

物事はうまくいきます。

確かに、一時的な文字列でこれを回避する方法が必要です。

編集:したがって、コンセンサスはconst std :: string&returnvalueを使用することです。

元のコードは問題ないはずだと誰もが言っていることは知っていますが、WindowsCEでMSVC2005に問題が発生しているのを見たことがありますが、CEボックスでのみです。Win32クロスコンパイルではありません。

4

4 に答える 4

6

あなたのコードは正常に動作するはずです。このテストケースから検出できない何か他の問題があります。おそらく、実行可能ファイルを valgrind で実行して、メモリ エラーを検索します。

于 2011-01-06T22:25:51.043 に答える
1

まあ、コードに問題はありません (私が解釈する限り)。それは最適ではなく、間違いなくそうではありませんThe Right Way (R)。villentehaspam が提案するようにコードを変更する必要があります。現状では、値で返すため、コードは文字列のコピーを作成m_valueします。これは、const 参照のみを返すほど良くありません。

問題を示す完全なコード サンプルを提供していただければ、より適切なサポートを提供できます。

于 2011-01-06T22:18:25.800 に答える
0

それは問題ではありませんが、そのクラスの std::string 戻り値は const を使用できます。それ以外の場合は、無駄なメンバー値のコピーを作成するだけです。

std::string value() const { return m_value; }
于 2011-01-07T17:02:26.267 に答える
-1

書き込み時に通常発生することは次のとおりです。

printf("value: %s\n", v1.value().c_str());
  1. コンパイラは、std::stringから返された値を保持する一時的な を作成しv1.value()ます。
  2. 戻り値を呼び出しv1.value()て一時文字列に入れます (正確な方法はさまざまです。通常、一時文字列への参照を隠しパラメーターとしてメソッドに渡します。http://en.wikipedia.org/wiki/を参照してください)。説明のためのReturn_value_optimization )。
  3. .c_str()一時的なを呼び出しstd::stringconst char *結果をどこかに隠します (例: レジスタ)。
  4. 一時的なstd::string.
  5. const char *(3)で取得したポインタを引数として渡しますprintf()

問題は、手順 3 のポインターが一時によって割り当てられたメモリを指していることですstd::string。これは、一時のデストラクタが呼び出されると解放されます。このメモリは、 によって使用されるまでには、長い間失われている可能性がありますprintf()

基本的に、あなたが示したような使用法は危険であり、避けるべきです. 次の使用は正しいです。

std::string copiedString = v1.value();
printf("value: %s\n", copiedString.c_str());

のデストラクタは、範囲外にcopiedStringなるまで呼び出されないためcopiedString、しばらくしprintf()てから戻ります。v1.value().c_str()実際、どちらの場合も一時std::stringが作成されるため、これは よりも効率的です。

文字列への参照を返すことは、呼び出し元が必要とする限り参照が有効である限り、優れた代替手段です。したがって、長寿命オブジェクトのメンバー変数への参照は問題ありません。一時的であることが判明したものへの参照はそうではありません。

于 2014-04-22T14:03:32.853 に答える