109

私のプログラムの 1 つで、const char*.

次のような構造があるとしましょう。

struct Foo
{
  const char* server;
  const char* name;
};

私の上位レベルのアプリケーションは のみを処理するため、ポインターを取得するためstd::stringに を使用することを考えました。std::string::c_str()const char*

しかし、の寿命はc_str()何ですか?

未定義の動作に直面することなく、このようなことを行うことはできますか?

{
  std::string server = "my_server";
  std::string name = "my_name";

  Foo foo;
  foo.server = server.c_str();
  foo.name = name.c_str();

  // We use foo
  use_foo(foo);

  // Foo is about to be destroyed, before name and server
}

または、結果をすぐc_str()に別の場所にコピーすることになっていますか?

ありがとうございました。

4

7 に答える 7

92

が破棄された場合、または文字列の非 const メンバー関数が呼び出されたc_str()場合、結果は無効になります。std::stringそのため、通常、保管する必要がある場合は、コピーを作成することをお勧めします。

あなたの例の場合、c_str()そのスコープ内では文字列が変更されないため、結果は安全に使用されているようです。(ただし、これらの値で何を行っているのかuse_foo()、または行っている可能性があるのか​​ はわかりません。文字列を別の場所にコピーする場合は、ポインターをコピーするだけでなく~Foo()、真のcopyを実行する必要があります。)char

于 2011-06-23T15:15:29.950 に答える
26

技術的には、あなたのコードは問題ありません。

しかし、コードを知らない人が簡単に壊れるような方法で書いています。c_str() の唯一の安全な使用法は、関数にパラメーターとして渡す場合です。そうしないと、メンテナンスの問題に直面することになります。

例 1:

{
  std::string server = "my_server";
  std::string name   = "my_name";

  Foo foo;
  foo.server = server.c_str();
  foo.name = name.c_str();

  //
  // Imagine this is a long function
  // Now a maintainer can easily come along and see name and server
  // and would never expect that these values need to be maintained as
  // const values so why not re-use them

  name += "Martin";
  // Oops now its broken.

  // We use foo
  use_foo(foo);

  // Foo is about to be destroyed, before name and server
}

したがって、メンテナンスのために次のことを明確にしてください。

より良い解決策:

{
  // Now they can't be changed.
  std::string const server = "my_server";
  std::string const name   = "my_name";

  Foo foo;
  foo.server = server.c_str();
  foo.name = name.c_str();

  use_foo(foo);    
}

ただし、const 文字列がある場合は、実際には必要ありません。

{
  char const* server = "my_server";
  char const* name   = "my_name";

  Foo foo;
  foo.server = server;
  foo.name   = name;

  use_foo(foo);
}

わかった。何らかの理由でそれらを文字列として使用したい場合
: 呼び出しでのみ使用しない理由:

{
  std::string server = "my_server";
  std::string name = "my_name";

  // guaranteed not to be modified now!!!     
  use_foo(Foo(server.c_str(), name.c_str());
}
于 2011-06-23T16:07:16.210 に答える
7

string対応するオブジェクトに次のいずれかが発生するまで有効です。

  • オブジェクトが破壊される
  • オブジェクトが変更されました

s がコピーされた後、が呼び出される前にこれらのstringオブジェクトを変更しない限り、コードに問題はありません。c_str()foouse_foo()

于 2011-06-23T15:15:23.710 に答える
4

c_str() の戻り値は、同じ文字列に対する非定数メンバー関数の次の呼び出しまでのみ有効です。

于 2011-06-23T15:15:11.740 に答える
3

const char*返された fromは、オブジェクトc_str()への次の非 const 呼び出しまでのみ有効です。std::stringこの場合std::string、 の存続期間中はスコープ内にあり、Foofoo の使用中に文字列を変更する他の操作を行っていないため、問題ありません。

于 2011-06-23T15:18:04.700 に答える
2

文字列が破壊または変更されない限り、c_str() を使用しても問題ありません。以前に返された c_str() を使用して文字列が変更された場合、実装定義です。

于 2011-06-23T15:15:07.023 に答える