Std :: string :: c_str () yaşam süresi nedir?


100

Programlarımdan birinde, birlikte çalışan bazı eski kodlarla arayüz oluşturmam gerekiyor const char* .

Şöyle görünen bir yapım olduğunu varsayalım:

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

Üst düzey uygulamam sadece ilgileniyor std::string, bu yüzden işaretçileri std::string::c_str()geri almak için kullanmayı düşündüm const char*.

Ama ömrü ne kadar c_str() ?

Tanımlanmamış davranışlarla karşılaşmadan böyle bir şey yapabilir miyim?

{
  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
}

Yoksa hemen sonucunu kopyalamam mı gerekiyor? c_str() başka bir yere ?

Teşekkür ederim.


Bir işlevde yerel bir dizge tanımladığımda ve geri döndüğümde başıma geldi .c_str(). Neden bazen dizenin sadece bazı kısımlarını aldığımı anlamadım, ta ki const char*sonsuza kadar yaşamayacağını anlayana kadar, ancak dizi yok olana kadar
SomethingSomething

Yanıtlar:


85

c_str()Sonuç ise geçersiz olurstd::string yok edilir veya dize bir const olmayan üye işlev adı verilir. Dolayısıyla, etrafta tutmanız gerekiyorsa, genellikle bir kopyasını almak isteyeceksiniz.

Örneğinizde, sonuçlarının c_str()güvenli bir şekilde kullanıldığı görülmektedir, çünkü bu kapsamda dizeler değiştirilmez. (Bununla birlikte, bu değerlerle ne use_foo()ya ~Foo()da ne yapıyor olabileceğini bilmiyoruz ; dizeleri başka bir yere kopyalıyorlarsa, o zaman gerçek bir kopya yapmalılar , sadece charişaretçileri kopyalamamalılar .)


std :: string nesnesi, kapsam dışına çıkan otomatik bir nesneyse veya bir evre oluşturma işlevi çağrısı içindeyse c_str () işaretçisi geçersiz olabilir.
GuruM

Lütfen açıklar non-const member function of the string is called.mısınız?
Mathew Kurian

2
"Sabit olmayan üye işlev", constanahtar sözcükle işaretlenmemiş herhangi bir üye işlevdir . Böyle bir işlev, dizgenin içeriğini değiştirebilir, bu durumda dizenin, tarafından döndürülen dizenin boş sonlandırılmış sürümü için belleği yeniden tahsis etmesi gerekebilir c_str(). Örneğin, size()ve length()vardır constsen değişen dize konusunda endişelenmeden diyoruz, ancak bunu, clear()değil const.
Kristopher Johnson

23

Teknik olarak kodunuz iyi.

ANCAK , kodu bilmeyen birinin kırılmasını kolaylaştıracak şekilde yazdınız. C_str () için tek güvenli kullanım, onu bir işleve parametre olarak ilettiğiniz zamandır. Aksi takdirde kendinizi bakım sorunlarına açarsınız.

Örnek 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
}

Yani bakım için bunu açıkça belirtin:

Daha iyi çözüm:

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

Ancak sabit dizeleriniz varsa aslında onlara ihtiyacınız yoktur:

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

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

  use_foo(foo);
}

TAMAM. Bazı nedenlerden dolayı onları dizge olarak istiyorsun:
Neden onları sadece görüşmede kullanmıyorsun:

{
  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

Aşağıdakilerden biri karşılık gelen stringnesneye gelene kadar geçerlidir :

  • nesne yok edildi
  • nesne değiştirildi

Bu stringnesneleri c_str()kopyalandıktan sonra fooancak use_foo()çağrılmadan önce değiştirmediğiniz sürece kodunuzda sorun yoktur .


4

C_str () dönüş değeri yalnızca aynı dizge için sabit olmayan bir üye işlevinin bir sonraki çağrısına kadar geçerlidir


3

const char*Dönen c_str()bir sonraki const olmayan çağrısına kadar tek geçerli olan std::stringnesne. Bu durumda iyisiniz, çünkü std::stringyaşamınız boyunca hala kapsam içindesiniz Foove foo kullanırken dizgiyi değiştirecek başka işlemler yapmıyorsunuz.


2

Dizge yok edilmediği veya değiştirilmediği sürece, c_str () kullanmak tamamdır. Dizge önceden döndürülen bir c_str () kullanılarak değiştirilirse, uygulama tanımlanır.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.