क्या है 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*यह नहीं समझ पाया कि यह हमेशा के लिए नहीं रहता है, लेकिन जब तक स्ट्रिंग नष्ट नहीं हो जाती
कुछ नहीं होगा।

जवाबों:


85

यदि c_str()परिणाम std::stringनष्ट हो जाता है या यदि स्ट्रिंग के गैर-सदस्य सदस्य फ़ंक्शन को कॉल किया जाता है, तो परिणाम अमान्य हो जाता है। इसलिए, यदि आप इसे इधर-उधर रखना चाहते हैं, तो आमतौर पर आप इसकी एक प्रति बनाना चाहेंगे।

आपके उदाहरण के मामले में, ऐसा प्रतीत होता है कि परिणाम c_str()सुरक्षित रूप से उपयोग किए जाते हैं, क्योंकि उस दायरे में रहते हुए तार को संशोधित नहीं किया जाता है। (हालांकि, हम नहीं जानते कि उन मूल्यों के साथ क्या हो सकता है use_foo()या ~Foo()हो सकता है; यदि वे तार कहीं और कॉपी करते हैं, तो उन्हें एक सच्ची कॉपी करना चाहिए , और न केवल बिंदुओं को कॉपी करना चाहिए char।)


c_str () पॉइंटर अवैध हो सकता है अगर std :: string ऑब्जेक्ट एक स्वचालित ऑब्जेक्ट है जो कार्यक्षेत्र से बाहर जा रहा है या थ्रेड फ़ंक्शन के लिए कॉल करता है।
गुरु अष्टम

क्या आप समझा सकते हैं non-const member function of the string is called.?
मैथ्यू कुरियन

2
"नॉन-कास्ट मेंबर फंक्शन" कोई भी मेम्बर फंक्शन होता है जो constकीवर्ड से चिह्नित नहीं होता है । ऐसा फ़ंक्शन स्ट्रिंग की सामग्री को म्यूट कर सकता है, जिस स्थिति में स्ट्रिंग द्वारा लौटे स्ट्रिंग के अशक्त-समाप्त संस्करण के लिए मेमोरी को पुनः लोड करने की आवश्यकता हो सकती है c_str()। उदाहरण के लिए, size()और length()हैं const, इसलिए आप उन्हें स्ट्रिंग बदलने की चिंता किए बिना कॉल कर सकते हैं, लेकिन clear()ऐसा नहीं है const
क्रिस्टोफर जॉनसन

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

लेकिन अगर आपके पास तार हैं तो आपको वास्तव में उनकी आवश्यकता नहीं है:

{
  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वस्तु के लिए न हो जाए:

  • वस्तु नष्ट हो जाती है
  • वस्तु संशोधित है

आप अपने कोड के साथ ठीक हैं जब तक कि आप उन stringवस्तुओं को संशोधित नहीं करते हैं जब तक कि c_str()एस को कॉपी नहीं किया जाता है fooलेकिन पहले use_foo()कहा जाता है।


4

C_str () का रिटर्न मान केवल तब तक ही मान्य है जब तक कि एक ही स्ट्रिंग के लिए एक गैर-असंबद्ध सदस्य फ़ंक्शन का अगला कॉल न हो


3

const char*लौटे से c_str()केवल अगले गैर स्थिरांक कॉल जब तक के लिए वैध है std::stringवस्तु। इस मामले में आप ठीक हैं क्योंकि आपका std::stringअभी भी जीवन भर के लिए गुंजाइश है Fooऔर आप कोई अन्य ऑपरेशन नहीं कर रहे हैं जो फू का उपयोग करते समय स्ट्रिंग को बदल देगा।


2

जब तक स्ट्रिंग को नष्ट नहीं किया जाता या संशोधित नहीं किया जाता है, तब तक c_str () का उपयोग करना ठीक है। यदि स्ट्रिंग पहले से लौटे c_str () का उपयोग करके संशोधित की गई है तो कार्यान्वयन परिभाषित है।


2

पूर्णता के लिए, यहाँ एक संदर्भ और cppreference.com से उद्धरण है :

इससे प्राप्त सूचक को c_str()अमान्य किया जा सकता है:

  • किसी भी मानक लायब्रेरी फ़ंक्शन, या के लिए स्ट्रिंग के लिए एक गैर-कॉन्स्टिट्यूशन पासिंग
  • पर गैर स्थिरांक सदस्य कार्यों कॉलिंग string, को छोड़कर operator[], at(), front(), back(), begin(), rbegin(), end()और rend()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.