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


100

내 프로그램 중 하나에서 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(). 나는 const char*영원히 살지 않는다는 것을 이해할 때까지 때때로 끈의 일부만 얻는 이유를 이해하지 못했지만 끈이 파괴 될 때까지
SomethingSomething

답변:


85

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

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


std :: string 객체가 범위를 벗어나거나 스레드 생성 함수를 호출하는 자동 객체 인 경우 c_str () 포인터가 유효하지 않을 수 있습니다.
GuruM

설명해 주 non-const member function of the string is called.시겠습니까?
Mathew Kurian

2
"비상 수 멤버 함수"는 const키워드 로 표시되지 않은 멤버 함수입니다 . 이러한 함수는 문자열의 내용을 변경할 수 있으며,이 경우 문자열은에서 반환 된 문자열의 null로 끝나는 버전에 대한 메모리를 재 할당해야 할 수 있습니다 c_str(). 예를 들어 size()length()are const이므로 문자열 변경에 대해 걱정하지 않고 호출 할 수 있지만 clear()그렇지 않습니다 const.
Kristopher Johnson

23

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

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

7

다음 중 하나가 해당 string개체에 발생할 때까지 유효 합니다.

  • 개체가 파괴되었습니다
  • 개체가 수정 됨

s가 복사 된 string후 호출 되기 전에 해당 개체 를 수정하지 않는 한 코드에 문제가 없습니다 .c_str()foouse_foo()


4

c_str ()의 반환 값은 동일한 문자열에 대해 상수가 아닌 멤버 함수를 다음에 호출 할 때까지만 유효합니다.


3

에서 const char*반환 된 c_str()std::string객체에 대한 다음 non-const 호출까지만 유효 합니다. 이 경우 당신 std::string은 여전히 ​​일생 동안 범위에 있고 Foofoo를 사용하는 동안 문자열을 변경하는 다른 작업을 수행하지 않기 때문에 괜찮습니다 .


2

문자열이 파괴되거나 수정되지 않는 한 c_str () 사용은 괜찮습니다. 이전에 반환 된 c_str ()을 사용하여 문자열을 수정하면 구현이 정의됩니다.


2

완전성을 위해 다음 은 cppreference.com참조 및 인용입니다 .

에서 얻은 포인터 c_str()는 다음에 의해 무효화 될 수 있습니다.

  • 문자열에 대한 상수가 아닌 참조를 표준 라이브러리 함수에 전달하거나
  • 온 비 const 멤버 함수 호출 string을 제외한, operator[], at(), front(), back(), begin(), rbegin(), end()rend().
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.