programing tip

std :: string :: c_str () 수명이란 무엇입니까?

itbloger 2020. 9. 6. 08:50
반응형

std :: string :: c_str () 수명이란 무엇입니까?


내 프로그램 중 하나에서 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()를 다른 곳에 즉시 복사해야 합니까?

감사합니다.


c_str()(가) 경우 결과가 유효하게 std::string파괴 또는 문자열의 비 CONST 멤버 함수가 호출되는 경우. 따라서 일반적으로 보관해야 할 경우 복사본을 만들고 싶을 것입니다.

귀하의 예제의 경우 c_str()해당 범위 내에서 문자열이 수정되지 않기 때문에의 결과 가 안전하게 사용되는 것으로 보입니다 . (그러나, 우리는 모르는 use_foo()또는 ~Foo()그 값으로 일을 할 수있는, 그들은 다른 곳에서 문자열을 복사 할 경우, 그들은 진정한해야 사본을 , 그냥 복사하지 char포인터를.)


기술적으로 코드는 괜찮습니다.

그러나 당신은 코드를 모르는 누군가를 위해 쉽게 깨뜨리는 방식으로 작성했습니다. 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);
}

OK. For some reason you want them as strings:
Why not use them only in the call:

{
  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());
}

It is valid until one of the following happens to the corresponding string object:

  • the object is destroyed
  • the object is modified

You're fine with your code unless you modify those string objects after c_str()s are copied into foo but before use_foo() is called.


Return value of c_str() is valid only until the next call of a nonconstant member function for the same string


The const char* returned from c_str() is only valid until the next non-const call to the std::string object. In this case you're fine because your std::string is still in scope for the lifetime of Foo and you aren't doing any other operations that would change the string while using foo.


As long as the string isn't destroyed or modified, using c_str() is OK. If the string is modified using a previously returned c_str() is implementation defined.


For completeness, here's a reference and quotation from cppreference.com:

The pointer obtained from c_str() may be invalidated by:

  • Passing a non-const reference to the string to any standard library function, or
  • Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and rend().

참고URL : https://stackoverflow.com/questions/6456359/what-is-stdstringc-str-lifetime

반응형