ฉันจะแปลง an std::stringเป็นchar*หรือ a ได้const char*อย่างไร

ตอบ

หากคุณต้องการส่งผ่านstd::stringไปยังฟังก์ชั่นที่ต้องการconst char*คุณสามารถใช้

std::string str;
const char * c = str.c_str();

หากคุณต้องการได้รับสำเนาที่เขียนได้ เช่นchar *คุณสามารถทำได้ด้วยสิ่งนี้:

std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0

// don't forget to free the string after finished using it
delete[] writable;

แก้ไข : ขอให้สังเกตว่าข้างต้นไม่มีข้อยกเว้น หากมีสิ่งใดเกิดขึ้นระหว่างการnewโทรและการdeleteโทรออก หน่วยความจำจะรั่วไหล เนื่องจากจะไม่มีสิ่งใดเรียกdeleteหาคุณโดยอัตโนมัติ มีสองวิธีในการแก้ปัญหานี้ทันที

เพิ่ม::scoped_array

boost::scoped_array จะลบหน่วยความจำให้คุณเมื่ออยู่นอกขอบเขต:

std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0

// get the char* using writable.get()

// memory is automatically freed if the smart pointer goes 
// out of scope

std::เวกเตอร์

นี่เป็นวิธีมาตรฐาน (ไม่ต้องใช้ไลบรารี่ภายนอก) คุณใช้std::vectorซึ่งจัดการหน่วยความจำให้คุณอย่างสมบูรณ์

std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');

// get the char* using &writable[0] or &*writable.begin()

ให้พูด...

std::string x = "hello";

รับ `char *` หรือ `const char*` จาก `string`

วิธีรับตัวชี้อักขระที่ถูกต้องในขณะที่xยังคงอยู่ในขอบเขตและไม่ได้รับการแก้ไขเพิ่มเติม

C++11ทำให้สิ่งต่าง ๆ ง่ายขึ้น ทั้งหมดต่อไปนี้ให้การเข้าถึงบัฟเฟอร์สตริงภายในเดียวกัน:

const char* p_c_str = x.c_str();
const char* p_data  = x.data();
char* p_writable_data = x.data(); // for non-const x from C++17 
const char* p_x0    = &x[0];

      char* p_x0_rw = &x[0];  // compiles iff x is not const...

ตัวชี้ด้านบนทั้งหมดจะเก็บค่าเดียวกัน - ที่อยู่ของอักขระตัวแรกในบัฟเฟอร์ แม้แต่สตริงว่างก็มี "อักขระตัวแรกในบัฟเฟอร์" เนื่องจาก C++11 รับประกันว่าจะเก็บอักขระเทอร์มิเนเตอร์ NUL/0 พิเศษไว้เสมอหลังจากเนื้อหาสตริงที่กำหนดอย่างชัดเจน (เช่นstd::string("this\0that", 9)จะมีบัฟเฟอร์ที่เก็บ"this\0that\0")

รับคำแนะนำใด ๆ ข้างต้น:

char c = p[n];   // valid for n <= x.size()
                 // i.e. you can safely read the NUL at p[x.size()]

เฉพาะสำหรับไม่ใช่constตัวชี้p_writable_dataและจาก&x[0]:

p_writable_data[n] = c;
p_x0_rw[n] = c;  // valid for n <= x.size() - 1
                 // i.e. don't overwrite the implementation maintained NUL

การเขียน NUL ที่อื่นในสตริงจะไม่เปลี่ยนstring's size(); stringได้รับอนุญาตให้มี NUL จำนวนเท่าใดก็ได้ โดยจะไม่ได้รับการดูแลเป็นพิเศษโดยstd::string(เหมือนกันใน C++03)

ในC++03สิ่งต่าง ๆ ซับซ้อนกว่ามาก ( เน้นความแตกต่างที่สำคัญ ):

  • x.data()

    • กลับconst char*ไปที่บัฟเฟอร์ภายในของสตริงซึ่งมาตรฐานไม่ได้กำหนดให้ต้องลงท้ายด้วย NUL (เช่น อาจ['h', 'e', 'l', 'l', 'o']ตามด้วยค่าที่ไม่ได้เริ่มต้นหรือค่าขยะ โดยมีการเข้าถึงโดยไม่ได้ตั้งใจซึ่งมีพฤติกรรมที่ไม่ได้กำหนดไว้ )
      • x.size()ตัวอักษรมีความปลอดภัยในการอ่านคือx[0]ผ่านx[x.size() - 1]
      • สำหรับสตริงว่าง คุณรับประกันว่าพอยน์เตอร์ที่ไม่ใช่ค่า NULL บางตัวสามารถเพิ่ม 0 ได้อย่างปลอดภัย (ไชโย!) แต่คุณไม่ควรละเลยตัวชี้นั้น
  • &x[0]

    • สำหรับสตริงว่างมีพฤติกรรมที่ไม่ได้กำหนด (21.3.4)
      • เช่นให้f(const char* p, size_t n) { if (n == 0) return; ...whatever... }คุณไม่ต้องโทรf(&x[0], x.size());เมื่อx.empty()- เพียงแค่ใช้f(x.data(), ...).
    • อย่างอื่นตามx.data()แต่:
      • สำหรับ non- const xนี้ให้ผลลัพธ์ non- const char*pointer; คุณสามารถเขียนทับเนื้อหาสตริงได้
  • x.c_str()

    • ส่งกลับค่าconst char*ASCIIZ (สิ้นสุดด้วย NUL) ของค่า (เช่น ['h', 'e', ​​'l', 'l', 'o', '\0'])
    • แม้ว่าจะมีน้อยถ้ามีการใช้งานใด ๆ เลือกที่จะทำเช่นนั้น มาตรฐาน C++03 ได้รับการกำหนดเพื่อให้การใช้งานสตริงมีอิสระในการสร้างบัฟเฟอร์ NUL-terminated ที่ชัดเจนได้ทันทีจากบัฟเฟอร์ที่สิ้นสุดที่ไม่ใช่ NUL "เปิดเผย" โดยx.data()และ&x[0]
    • x.size() +1 ตัวอักษรปลอดภัยในการอ่าน
    • รับประกันความปลอดภัยแม้สำหรับสตริงที่ว่างเปล่า (['\0'])

ผลที่ตามมาของการเข้าถึงดัชนีทางกฎหมายภายนอก

ไม่ว่าคุณจะรับพอยน์เตอร์ด้วยวิธีใดก็ตาม คุณต้องไม่เข้าถึงหน่วยความจำเพิ่มเติมจากตัวชี้ไปเกินกว่าอักขระที่รับประกันว่าจะมีอยู่ในคำอธิบายด้านบน ความพยายามในการดำเนินการดังกล่าวมีพฤติกรรมที่ไม่ได้กำหนดซึ่งมีโอกาสมากที่แอปพลิเคชันจะขัดข้องและผลลัพธ์ที่เป็นขยะ แม้กระทั่งสำหรับการอ่าน และนอกจากนี้ ข้อมูลขายส่ง สแต็คความเสียหาย และ/หรือช่องโหว่ด้านความปลอดภัยสำหรับการเขียน

พอยน์เตอร์เหล่านั้นจะถูกยกเลิกเมื่อใด

ถ้าคุณเรียกบางstringฟังก์ชั่นของสมาชิกที่ปรับเปลี่ยนstringหรือสำรองความจุเพิ่มเติมค่าตัวชี้ใด ๆ กลับมาก่อนโดยใด ๆ ของวิธีการดังกล่าวเป็นโมฆะ คุณสามารถใช้วิธีการเหล่านั้นอีกครั้งเพื่อรับตัวชี้อื่น (กฎจะเหมือนกับการวนซ้ำเป็นstrings)

ดูเพิ่มเติมวิธีรับตัวชี้อักขระที่ถูกต้องแม้หลังจากxออกจากขอบเขตหรือแก้ไขเพิ่มเติมด้านล่าง....

แล้วอันไหนดีกว่าที่จะใช้?

จาก C++11 ใช้.c_str()สำหรับข้อมูล ASCIIZ และ.data()สำหรับข้อมูล "ไบนารี" (อธิบายเพิ่มเติมด้านล่าง)

ใน C++03 ให้ใช้.c_str()เว้นแต่แน่ใจว่า.data()เพียงพอและต้องการ.data()มากกว่า&x[0]เพราะปลอดภัยสำหรับสตริงว่าง....

...พยายามทำความเข้าใจโปรแกรมให้เพียงพอเพื่อนำไปใช้data()ตามความเหมาะสม มิฉะนั้น ท่านอาจทำผิดพลาดประการอื่นๆ...

อักขระ ASCII NUL '\0' ที่รับรองโดย.c_str()ถูกใช้โดยหลายฟังก์ชันเป็นค่ารักษาการณ์ซึ่งแสดงถึงจุดสิ้นสุดของข้อมูลที่เกี่ยวข้องและปลอดภัยต่อการเข้าถึง สิ่งนี้ใช้กับทั้งฟังก์ชัน C++ เท่านั้นเช่นฟังก์ชัน say fstream::fstream(const char* filename, ...)และ shared-with-C เช่นstrchr(), และprintf().

การ.c_str()รับประกันของ C++03 เกี่ยวกับบัฟเฟอร์ที่ส่งคืนนั้นเป็นชุดของ super-set .data()คุณสามารถใช้ได้อย่างปลอดภัย.c_str()แต่บางครั้งผู้คนไม่ได้เพราะ:

  • ใช้.data()สื่อสารกับโปรแกรมเมอร์คนอื่น ๆ ที่อ่านซอร์สโค้ดว่าข้อมูลนั้นไม่ใช่ ASCIIZ (แต่คุณกำลังใช้สตริงเพื่อจัดเก็บบล็อกของข้อมูล ฟังก์ชันอื่นที่ถือว่าเป็นบล็อกของข้อมูล "ไบนารี" นี่อาจเป็นข้อมูลเชิงลึกที่สำคัญในการตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงโค้ดของโปรแกรมเมอร์คนอื่นๆ ยังคงจัดการกับข้อมูลได้อย่างถูกต้อง
  • C++03 เท่านั้น: มีโอกาสเล็กน้อยที่stringการใช้งานของคุณจะต้องทำการจัดสรรหน่วยความจำเพิ่มเติมและ/หรือคัดลอกข้อมูลเพื่อเตรียม NUL ยุติบัฟเฟอร์

เป็นคำแนะนำเพิ่มเติม หากพารามิเตอร์ของฟังก์ชันต้องการ ( const) char*แต่ไม่ยืนยันว่าจะได้รับx.size()ฟังก์ชันอาจต้องการอินพุต ASCIIZ ดังนั้นจึง.c_str()เป็นตัวเลือกที่ดี (ฟังก์ชันจำเป็นต้องรู้ว่าข้อความสิ้นสุดที่ใด ดังนั้นหากไม่ใช่ พารามิเตอร์ที่แยกจากกันสามารถเป็นแบบแผนเช่นคำนำหน้าความยาวหรือยามรักษาการณ์หรือความยาวที่คาดไว้บางส่วนเท่านั้น)

วิธีรับตัวชี้อักขระที่ถูกต้องแม้หลังจากxออกจากขอบเขตหรือได้รับการแก้ไขเพิ่มเติม

คุณจะต้องคัดลอกเนื้อหาของการที่อยู่นอกพื้นที่หน่วยความจำใหม่string x xบัฟเฟอร์ภายนอกนี้อาจอยู่ในหลายที่ เช่นstringตัวแปรอาร์เรย์อื่นหรืออาร์เรย์อักขระ อาจมีหรือไม่มีอายุการใช้งานที่แตกต่างxจากเนื่องจากอยู่ในขอบเขตที่แตกต่างกัน (เช่น เนมสเปซ โกลบอล สแตติก ฮีป หน่วยความจำที่ใช้ร่วมกัน ไฟล์ที่แมปหน่วยความจำ) .

ในการคัดลอกข้อความจากstd::string xไปยังอาร์เรย์อักขระอิสระ:

// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;
// - old_x will not be affected by subsequent modifications to x...
// - you can use `&old_x[0]` to get a writable char* to old_x's textual content
// - you can use resize() to reduce/expand the string
//   - resizing isn't possible from within a function passed only the char* address

std::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL
// Copies ASCIIZ data but could be less efficient as it needs to scan memory to
// find the NUL terminator indicating string length before allocating that amount
// of memory to copy into, or more efficient if it ends up allocating/copying a
// lot less content.
// Example, x == "ab\0cd" -> old_x == "ab".

// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data() + x.size());       // without the NUL
std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1);  // with the NUL

// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"
// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)
char y[N + 1];
strcpy(y, x.c_str());

// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)
char y[N + 1];
strncpy(y, x.c_str(), N);  // copy at most N, zero-padding if shorter
y[N] = '\0';               // ensure NUL terminated

// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH
char* y = alloca(x.size() + 1);
strcpy(y, x.c_str());

// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)
char y[x.size() + 1];
strcpy(y, x.c_str());

// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = new char[x.size() + 1];
strcpy(y, x.c_str());
//     or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
// use y...
delete[] y; // make sure no break, return, throw or branching bypasses this

// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE
// see boost shared_array usage in Johannes Schaub's answer

// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);

เหตุผลอื่น ๆ ที่ต้องการchar*หรือconst char*สร้างขึ้นจาก astring

ดังนั้น ด้านบน คุณได้เห็นวิธีรับ ( const) char*และวิธีสร้างสำเนาข้อความโดยไม่ขึ้นกับต้นฉบับstringแต่คุณจะทำอะไรกับข้อความนี้ได้ สุ่มตัวอย่างคร่าวๆ...

  • ให้รหัส "C" เข้าถึงข้อความของ C++ stringเช่นเดียวกับในprintf("x is '%s'", x.c_str());
  • คัดลอกxข้อความไปยังบัฟเฟอร์ที่ระบุโดยผู้เรียกใช้ฟังก์ชันของคุณ (เช่นstrncpy(callers_buffer, callers_buffer_size, x.c_str())) หรือหน่วยความจำระเหยที่ใช้สำหรับอุปกรณ์ I/O (เช่นfor (const char* p = x.c_str(); *p; ++p) *p_device = *p;)
  • ต่อท้ายxข้อความในอาร์เรย์อักขระที่มีข้อความ ASCIIZ อยู่แล้ว (เช่นstrcat(other_buffer, x.c_str())) - ระวังอย่าโอเวอร์รันบัฟเฟอร์ (ในหลายสถานการณ์ คุณอาจต้องใช้strncat)
  • ส่งคืน a const char*หรือchar*จากฟังก์ชัน (อาจเป็นเพราะเหตุผลในอดีต - ลูกค้าใช้ API ที่มีอยู่ของคุณ - หรือเพื่อความเข้ากันได้ของ C คุณไม่ต้องการส่งคืน a std::stringแต่ต้องการคัดลอกข้อมูลของคุณstringที่ใดที่หนึ่งสำหรับผู้โทร)
    • ระวังอย่าส่งคืนพอยน์เตอร์ที่ผู้เรียกอาจถูกปฏิเสธหลังจากstringตัวแปรโลคัลที่ตัวชี้ชี้นั้นออกจากขอบเขต
    • บางโปรเจ็กต์ที่มีอ็อบเจ็กต์ที่ใช้ร่วมกันถูกคอมไพล์/ลิงก์สำหรับstd::stringการใช้งานที่แตกต่างกัน(เช่น STLport และคอมไพเลอร์-เนทีฟ) อาจส่งข้อมูลเป็น ASCIIZ เพื่อหลีกเลี่ยงความขัดแย้ง

ใช้.c_str()วิธีการสำหรับconst char *.

คุณสามารถใช้&mystring[0]เพื่อรับchar *ตัวชี้ แต่มี gotcha อยู่สองสามตัว: คุณไม่จำเป็นต้องได้รับสตริงที่สิ้นสุดเป็นศูนย์ และคุณจะไม่สามารถเปลี่ยนขนาดของสตริงได้ คุณต้องระวังเป็นพิเศษอย่าเพิ่มอักขระที่อยู่หลังจุดสิ้นสุดของสตริง มิฉะนั้น คุณจะได้รับบัฟเฟอร์โอเวอร์รัน (และอาจเกิดความผิดพลาด)

ไม่มีการรับประกันว่าอักขระทั้งหมดจะเป็นส่วนหนึ่งของบัฟเฟอร์ที่ต่อเนื่องกันจนถึง C++11 แต่ในทางปฏิบัติแล้ว การใช้งานที่รู้จักทั้งหมดstd::stringนั้นทำงานในลักษณะนั้นอยู่แล้ว ดู“&s[0]” ชี้ไปที่อักขระต่อเนื่องกันใน std::string หรือไม่ .

โปรดทราบว่าstringฟังก์ชันสมาชิกจำนวนมากจะจัดสรรบัฟเฟอร์ภายในใหม่และทำให้พอยน์เตอร์ที่คุณอาจบันทึกไว้ใช้ไม่ได้ ควรใช้ทันทีแล้วทิ้ง

C++17

C++17 (มาตรฐานที่กำลังจะมีขึ้น) เปลี่ยนบทสรุปของเทมเพลตที่basic_stringเพิ่มการโอเวอร์โหลดที่ไม่ใช่ const ของdata():

charT* data() noexcept;

Returns: A pointer p such that p + i == &operator for each i in [0,size()].


CharT const * จาก std::basic_string<CharT>

std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()

CharT * จาก std::basic_string<CharT>

std::string str = { "..." };
char * p = str.data();

C++11

CharT const * จาก std::basic_string<CharT>

std::string str = { "..." };
str.c_str();

CharT * จาก std::basic_string<CharT>

ตั้งแต่ C++11 เป็นต้นไป มาตรฐานระบุว่า:

  1. The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0 <= n < s.size().

  1. const_reference operator[](size_type pos) const;
    reference operator[](size_type pos);

    Returns: *(begin() + pos) if pos < size(), otherwise a reference to an object of type CharT with value CharT(); the referenced value shall not be modified.


  1. const charT* c_str() const noexcept;
    const charT* data() const noexcept;

    Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].

มีหลายวิธีที่เป็นไปได้ในการรับตัวชี้อักขระที่ไม่ใช่ const

1. ใช้ที่เก็บข้อมูล C++11 . ที่ต่อเนื่องกัน

std::string foo{"text"};
auto p = &*foo.begin();

มือโปร

  • เรียบง่ายและสั้น
  • รวดเร็ว (วิธีเดียวที่ไม่เกี่ยวข้องกับการคัดลอก)

ข้อเสีย

  • ขั้นสุดท้าย'\0'จะไม่ถูกแก้ไข / ไม่จำเป็นต้องเป็นส่วนหนึ่งของหน่วยความจำแบบ non-const

2. ใช้ std::vector<CharT>

std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();

มือโปร

  • เรียบง่าย
  • การจัดการหน่วยความจำอัตโนมัติ
  • พลวัต

ข้อเสีย

  • ต้องการการคัดลอกสตริง

3. ใช้std::array<CharT, N>if Nเป็นค่าคงที่เวลาคอมไพล์ (และเล็กพอ)

std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());

มือโปร

  • เรียบง่าย
  • การจัดการหน่วยความจำสแต็ค

ข้อเสีย

  • คงที่
  • ต้องการการคัดลอกสตริง

4. การจัดสรรหน่วยความจำดิบพร้อมการลบที่เก็บข้อมูลอัตโนมัติ

std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);

มือโปร

  • รอยเท้าหน่วยความจำขนาดเล็ก
  • การลบอัตโนมัติ
  • เรียบง่าย

ข้อเสีย

  • ต้องการการคัดลอกสตริง
  • คงที่ (การใช้งานไดนามิกต้องใช้รหัสมากขึ้น)
  • คุณสมบัติน้อยกว่าเวกเตอร์หรืออาร์เรย์

5. การจัดสรรหน่วยความจำดิบด้วยการจัดการด้วยตนเอง

std::string foo{ "text" };
char * p = nullptr;
try
{
  p = new char[foo.size() + 1u];
  std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
  // handle stuff with p
  delete[] p;
}
catch (...)
{
  if (p) { delete[] p; }
  throw;
}

มือโปร

  • 'การควบคุม' สูงสุด

กับ

  • ต้องการการคัดลอกสตริง
  • ความรับผิดสูงสุด / ความอ่อนไหวต่อข้อผิดพลาด
  • ซับซ้อน

เพียงแค่ดูสิ่งนี้:

string str1("stackoverflow");
const char * str2 = str1.c_str();

อย่างไรก็ตาม โปรดทราบว่าสิ่งนี้จะส่งกลับconst char *.

สำหรับ a char *ใช้strcpyเพื่อคัดลอกไปยังcharอาร์เรย์อื่น

ฉันกำลังทำงานกับ API ที่มีฟังก์ชันมากมายที่รับ a char*เป็นอินพุต

ฉันได้สร้างชั้นเรียนขนาดเล็กเพื่อเผชิญกับปัญหาประเภทนี้ และฉันได้ใช้สำนวนRAII

class DeepString
{
        DeepString(const DeepString& other);
        DeepString& operator=(const DeepString& other);
        char* internal_; 
    
    public:
        explicit DeepString( const string& toCopy): 
            internal_(new char[toCopy.size()+1]) 
        {
            strcpy(internal_,toCopy.c_str());
        }
        ~DeepString() { delete[] internal_; }
        char* str() const { return internal_; }
        const char* c_str()  const { return internal_; }
};

และคุณสามารถใช้เป็น:

void aFunctionAPI(char* input);

//  other stuff

aFunctionAPI("Foo"); //this call is not safe. if the function modified the 
                     //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str()); //this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string 
                                                //implement reference counting and 
                                                //it may change the value of other
                                                //strings as well.
DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str()); //this is fine

ฉันเรียกคลาสนี้DeepStringเพราะมันกำลังสร้างสำเนาที่ลึกและไม่ซ้ำใคร ( DeepStringซึ่งไม่สามารถคัดลอกได้) ของสตริงที่มีอยู่

char* result = strcpy((char*)malloc(str.length()+1), str.c_str());

สมมุติว่า string str="stack";

1) การแปลงสตริงเป็นถ่าน *

  char* s_rw=&str[0]; 

อักขระด้านบน*(เช่น s_rw) สามารถอ่านและเขียนได้ และชี้ไปยังที่อยู่พื้นฐานของสตริงซึ่งจำเป็นต้องแปลงเป็นอักขระ*

2) การแปลงสตริงเป็น const char *

   const char* s_r=&str[0];

const char* ด้านบน (เช่น s_r) สามารถอ่านได้ แต่เขียนไม่ได้ และชี้ไปยังที่อยู่พื้นฐานของสตริง

ลองนี่สิ

std::string s(reinterpret_cast<const char *>(Data), Size);