如何将std::字符串转换为const char*或char*

如何将std::string转换为char*const char*

1145777 次浏览

const char *使用.c_str()方法。

您可以使用&mystring[0]来获取char *指针,但有几个问题:您不一定会得到一个以零结尾的字符串,并且您将无法更改字符串的大小。您尤其必须小心不要添加超过字符串末尾的字符,否则您将获得缓冲区溢出(并可能崩溃)。

在C++11之前,不能保证所有字符都属于同一个连续缓冲区,但实际上所有已知的std::string实现都是这样工作的;参见“&s[0]”是否指向std::字符串中的连续字符?

请注意,许多string成员函数将重新分配内部缓冲区并使您可能保存的任何指针无效。最好立即使用它们,然后丢弃。

如果你只是想将#0传递给需要const char *的函数,你可以使用#2

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

如果你需要一个非constchar *,调用#1

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

.data()是在C++17中添加的。在此之前,您可以使用&str[0]

请注意,如果std::stringconst.data()将返回const char *,就像.c_str()一样。

如果字符串被销毁或重新分配内存,指针将变为无效。

指针指向以null结尾的字符串,并且终止符不计入str.size()。您不允许将非空字符分配给终止符。

鉴于说…

std::string x = "hello";

从字符串获取'char*'或'const char*'

如何在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++17const 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会改变stringsize()string允许包含任意数量的NULs-它们没有被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... },你不能在x.empty()时调用f(&x[0], x.size());-只需使用f(x.data(), ...)
    • 否则,按照x.data()但是:
      • 对于非constx,这会产生一个非constchar*指针;您可以覆盖字符串内容
  • x.c_str()

    • const char*返回到值的ASCIIZ(NUL终止)表示形式(即['h','e','l','l','o','\0'])。
    • 尽管很少有实现选择这样做,但C++03标准的措辞允许字符串实现自由地从x.data()&x[0]“暴露”的潜在非NUL终止缓冲区创建不同的NUL终止缓冲区在飞行
    • x.size()+1个字符可以安全读取。
    • 即使对于空字符串(['\0'])也保证安全。

访问外部法律索引的后果

无论您以何种方式获得指针,您都不能从指针访问比上述描述中保证存在的字符更远的内存。这样做的尝试有未定义行为,即使对于读取,应用程序崩溃和垃圾结果的可能性也非常大,此外还有批发数据、堆栈损坏和/或写入的安全漏洞。

这些指针什么时候失效?

如果你调用某个string成员函数来修改string或保留更多的容量,上述任何方法事先返回的任何指针值都是无效。你可以再次使用这些方法来获取另一个指针。(规则与进入string的迭代器相同)。

另见下文如何在#0离开范围或进一步修改后仍然有效的字符指针

那么,使用哪个更好呢?

从C++11开始,使用.c_str()表示ASCIIZ数据,使用.data()表示“二进制”数据(下面进一步解释)。

在C++03中,除非确定.data()足够,否则使用.c_str(),并且更喜欢.data()而不是&x[0],因为它对空字符串是安全的。

…尝试在适当的时候足够理解程序以使用data(),否则您可能会犯其他错误…

.c_str()保证的ASCII NUL'\0'字符被许多函数用作哨兵值,表示相关和安全访问数据的结束。这适用于仅C++函数,例如fstream::fstream(const char* filename, ...)和与C共享的函数,例如strchr()printf()

鉴于C++03的.c_str()对返回缓冲区的保证是.data()的超集,您总是可以安全地使用.c_str(),但人们有时不会,因为:

  • 使用.data()会让其他读取源代码的程序员知道数据不是ASCIIZ(更确切地说,你是在使用字符串存储数据块(有时甚至不是真正的文本)),或者你是在将其传递给另一个将其视为“二进制”数据块的函数。这对于确保其他程序员的代码更改继续正确处理数据至关重要。
  • 仅C++03:您的string实现可能需要进行一些额外的内存分配和/或数据复制,以准备NUL终止的缓冲区

作为进一步的提示,如果一个函数的参数需要(constchar*但不坚持得到x.size(),函数可能需要一个ASCIIZ输入,所以.c_str()是一个不错的选择(函数需要知道文本以某种方式终止的位置,所以如果它不是一个单独的参数,它只能是一个约定,如长度前缀或哨兵或一些固定的预期长度)。

如何在x离开范围或进一步修改后仍然有效的字符指针

您需要将stringx的内容复制x之外的新内存区域。此外部缓冲区可能位于许多地方,例如另一个string或字符数组变量,由于位于不同的范围(例如命名空间、全局、静态、堆、共享内存、内存映射文件),它可能具有也可能不具有与x不同的生命周期。

要将文本从std::string x复制到独立的字符数组中:

// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFEstd::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++03std::vector<char> old_x(x.data(), x.data() + x.size());       // without the NULstd::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 shortery[N] = '\0';               // ensure NUL terminated
// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTHchar* 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 SAFETYchar* 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 SAFETYchar* y = strdup(x.c_str());// use y...free(y);

想要从string生成char*const char*的其他原因

所以,在上面你已经看到了如何得到一个(constchar*,以及如何制作一个独立于原始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
  • 从函数返回const char*char*(可能是由于历史原因-客户端使用您现有的API-或者出于C兼容性,您不想返回std::string,但确实想将string的数据复制到调用者的某个地方)
    • 注意不要在指针指向的局部string变量离开作用域后返回可能被调用者取消引用的指针
    • 一些为不同的std::string实现(例如STLport和编译器本机)编译/链接共享对象的项目可能会将数据作为ASCIIZ传递以避免冲突

我正在使用一个带有许多函数的API,这些函数将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 crashstd::string myFoo("Foo");aFunctionAPI(myFoo.c_str()); //this is not compilingaFunctionAPI(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不可复制)。

看看这个:

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

但是,请注意,这将返回const char *

对于char *,使用strcpy将其复制到另一个char数组中。

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

C++17

C++17(即将推出的标准)更改了模板basic_string的概要,添加了data()的非const重载:

charT* data() noexcept;

返回:一个指针p,使得[0, size()]中每个i的p+i==&运算符。


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. basic_string对象中的类字符对象应连续存储。也就是说,对于任何basic_string对象s,标识&*(s.begin() + n) == &*s.begin() + n应适用于n的所有值,使得0 <= n < s.size()

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

    返回:*(begin() + pos)如果pos < size(),否则引用CharT类型的对象,值CharT();引用的值不得修改。


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

    返回:一个指针p,使得[0,size()]中的每个i都有p + i == &operator[](i)

有几种可能的方法来获取非const字符指针。

1.使用连续储存C++11

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

Pro

  • 简单而简短
  • 快速(唯一的方法,不涉及副本)

缺点

  • 最终'\0'不被改变/不一定是非常量存储器的一部分。

2.使用std::vector<CharT>

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

Pro

  • 简单
  • 自动内存处理
  • 动态

缺点

  • 需要字符串复制

3.如果N是编译时间常数(并且足够小),则使用std::array<CharT, N>

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

Pro

  • 简单
  • 堆栈内存处理

缺点

  • 静态
  • 需要字符串复制

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

Pro

  • 内存占用小
  • 自动删除
  • 简单

缺点

  • 需要字符串复制
  • 静态(动态使用需要更多代码)
  • 比向量或数组更少的特征

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 pdelete[] p;}catch (...){if (p) { delete[] p; }throw;}

Pro

  • 最大控制

Con

  • 需要字符串复制
  • 对错误的最大责任/易感性
  • 复杂

试试这个

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

比方说,string str="堆栈";

1)将字符串转换为char*

  char* s_rw=&str[0];

上面的char*(即s_rw)是可读可写的,指向基础需要转换为char的字符串的地址*

2)将字符串转换为const char*

   const char* s_r=&str[0];

上面的const char*(即s_r)可读但不可写,并指向字符串的基地址。

从c++std字符串转换为C样式字符串现在真的很容易。

为此,我们有string::copy函数,它可以轻松地将std字符串转换为C样式字符串。参考

string::copy串行函数参数

  1. 字符串指针
  2. 字符串大小,将复制多少个字符
  3. 位置,从字符复制开始的位置

另一件重要的事,

此函数不会在操作结束时附加空字符。因此,我们需要手动放置它。

代码考试在下面-

// char stringchar chText[20];
// c++ stringstring text =  "I am a Programmer";
// conversion from c++ string to char string// this function does not append a null character at the end of operationtext.copy(chText, text.size(), 0);
// we need to put it manuallychText[text.size()] = '\0';
// below statement prints "I am a Programmer"cout << chText << endl;

反之亦然从C样式字符串转换为C++std字符串要容易得多

有三种方法可以将C样式字符串转换为C++std字符串

第一个是使用构造函数,

char chText[20] = "I am a Programmer";// using constructorstring text(chText);

第二个是使用string::assign方法

// char stringchar chText[20] = "I am a Programmer";
// c++ stringstring text;
// convertion from char string to c++ string// using assign functiontext.assign(chText);

第三个是赋值操作符(=),其中字符串类使用运算符重载

// char stringchar chText[20] = "I am a Programmer";
// c++ string// convertion from char string to c++ string using assignment operator overloadingstring text = chText;

第三个也可以写如下-

// char stringchar chText[20] = "I am a Programmer";
// c++ stringstring text;

// convertion from char string to c++ stringtext = chText;

当将std::string的底层char*缓冲区传递给期望并写入char*缓冲区的C调用时,这尤其有用。这样您就可以两全其美!:C++std::string的细微之处以及它直接与您从C++调用的C库的可用性。

如何使用现代C++std::string作为C风格的读/写char*或只读空终止const char*

如何将std::string转换为char*const char*

尽管这是一个非常古老且高度赞成的问题,但我将要介绍的信息还没有得到很好的介绍,如果有的话,所以这是一个必要的补充,特别是是关于需要使用.resize()方法预分配底层C字符串的部分,如果你想将其用作可写缓冲区。

下面的所有用法都需要C++11或更高版本,除了#0调用,它需要C++17或更高版本。

要运行和测试下面的所有示例代码等,请参阅并在我的eRCaGuy_hello_world存储库中运行我的string__use_std_string_as_a_c_str_buffer.cpp文件。

快速总结:

#include <string>constexpr size_t BUFFER_SIZE = 100;std::string str;// IMPORTANT: pre-allocate the underlying buffer to guarantee what size it isstr.resize(BUFFER_SIZE);
// -----------------------------------------------------------------------------// Get read-writeable access to the underlying `char*` C-string at index i// -----------------------------------------------------------------------------
char* c_str1 = &str[i]; // <=== my favorite!char* c_str2 = str.data() + i;char* c_str3 = &(*str.begin()) + i;
// NB: the C-strings above are NOT guaranteed to be null-terminated, so manually// write in a null terminator at the index location where you want it if// desired. Ex://// 1. write a null terminator at some arbitrary position you choose (index 10// here)c_str1[10] = '\0';// 2. write a null terminator at the last guaranteed valid position in the// underlying C-string/array of charsc_str2[str.size() - i - 1] = '\0';
// -----------------------------------------------------------------------------// Get read-only access to the underlying `const char*` C-string at index i// -----------------------------------------------------------------------------const char* const_c_str1 = &str[i];const char* const_c_str2 = str.c_str() + i; // guaranteed to be null-terminated,// but not necessarily at the// position you desire; the// guaranteed null terminator will// be at index location// `str.size()`

总结:

如果你有急事,你需要:

  1. 底层缓冲区的可读写char* C字符串:只需使用下面代码示例中的A技术1部分:char* c_str1 = &str[i];
    1. 如果需要,请务必通过str.resize(BUFFER_SIZE)预分配底层缓冲区大小第一,仅此而已,以确保底层缓冲区足够大以满足您的需求。
  2. 底层缓冲区的只读const char* C字符串:使用与上面(const char* const_c_str1 = &str[i];)、const char* const_c_str1 = str.c_str() + i;相同的东西。
#include <string>
constexpr size_t BUFFER_SIZE = 100;
std::string str;// IMPORTANT: pre-allocate the underlying buffer to guarantee what size it isstr.resize(BUFFER_SIZE);
// =============================================================================// Now you can use the `std::string`'s underlying buffer directly as a C-string// =============================================================================
// ---------------------------------------------------------// A. As a read-writeable `char*` C-string// ---------------------------------------------------------
// Technique 1 [best option if using C++11]: array indexing using `operator[]`// to obtain a char, followed by obtaining its address with `&`// - Documentation://   https://en.cppreference.com/w/cpp/string/basic_string/operator_atchar* c_str1 = &str[0];char* c_str2 = &str[10];char* c_str3 = &str[33];// etc.
// Technique 2 [best option if using C++17]: use the `.data()` method to obtain// a `char*` directly.// - Documentation://   https://en.cppreference.com/w/cpp/string/basic_string/datachar* c_str11 = str.data();      // same as c_str1 abovechar* c_str12 = str.data() + 10; // same as c_str2 abovechar* c_str13 = str.data() + 33; // same as c_str3 above
// Technique 3 [fine in C++11 or later, but is awkward, so don't do this. It is// for demonstration and learning purposes only]: use the `.begin()` method to// obtain an iterator to the first char, and then use the iterator's// `operator*()` dereference method to obtain the iterator's `char`// `value_type`, and then take the address of that to obtain a `char*`// - Documentation://   - https://en.cppreference.com/w/cpp/string/basic_string/begin//   - https://en.cppreference.com/w/cpp/named_req/RandomAccessIteratorchar* c_str21 = &(*str.begin());      // same as c_str1 and c_str11 abovechar* c_str22 = &(*str.begin()) + 10; // same as c_str2 and c_str12 abovechar* c_str23 = &(*str.begin()) + 33; // same as c_str3 and c_str13 above

// ---------------------------------------------------------// B. As a read-only, null-terminated `const char*` C-string// ---------------------------------------------------------
// - Documentation://   https://en.cppreference.com/w/cpp/string/basic_string/c_str
const char* const_c_str1 = str.c_str();      // a const version of c_str1 aboveconst char* const_c_str2 = str.c_str() + 10; // a const version of c_str2 aboveconst char* const_c_str3 = str.c_str() + 33; // a const version of c_str3 above

请注意,您也可以使用.at(i).front()std::string方法,但我不会详细介绍这些方法,因为我认为我的示例已经足够了。关于它们的留档,请参阅:

  1. https://en.cppreference.com/w/cpp/string/basic_string/at
  2. https://en.cppreference.com/w/cpp/string/basic_string/front

详情:

另请参见上面的注释。我不打算介绍使用.at(i).front()std::string方法的技术,因为我认为我已经介绍的几种技术已经足够了。

1.使用std::string作为可读/可写char*

要使用C++std::string作为C风格的可写char*缓冲区,您必须首先使用.resize()预分配字符串的内部缓冲区以更改其.size()。请注意,使用.reserve()仅增加.capacity()是不够的!cppreference.com社区wiki页面#6正确地指出:

如果pos > size(),则行为未定义。

resize()方法是改变大小的方法,没有reserve()方法,它只改变capacity()

例如:

#include <cstring>  // `strcpy()`#include <iostream>#include <string>

constexpr size_t BUFFER_SIZE = 100;
std::string str;str.resize(BUFFER_SIZE);  // pre-allocate the underlying buffer// check the sizestd::cout << "str.size() = " << str.size() << "\n";

对于下面的所有示例,假设您有这些C字符串:

constexpr char cstr1[] = "abcde ";constexpr char cstr2[] = "fghijk";

一旦你用resize()预分配了一个足够大的底层缓冲区,你就可以访问底层缓冲区char*至少有3种方式:

  1. 技巧1[使用C++11时的最佳选择]:使用#0进行数组索引以获取char,然后使用#1获取其地址。例如:
    char* c_str;c_str = &str[0];c_str = &str[5];// etc.
    // Write these 2 C-strings into a `std::string`'s underlying bufferstrcpy(&str[0], cstr1);strcpy(&str[sizeof(cstr1) - 1], cstr2); // `- 1` to overwrite the first// null terminator
    // print the stringstd::cout << str << "\n"; // output: `abcde fghijk`
    如果你有一个指向std::string的指针怎么办?如果你有一个指向std::string的ptr,它必须先用*pstr取消引用,然后才能作为一个数组将operator[]作为&(*pstr)[0]索引到它,所以上面的语法变得有点尴尬。这是一个完整的例子:
    std::string str2;std::string* pstr = &str2;pstr->resize(BUFFER_SIZE);c_str = &(*pstr)[0]; // <=== dereference the ptr 1st before indexing into it// Or, to make the order of precedence// (https://en.cppreference.com/w/cpp/language/operator_precedence) really// obvious, you can optionally add extra parenthesis like this:c_str = &((*pstr)[0]);
  2. 技巧2[使用C++17时的最佳选择]:使用#0方法直接获得#1。例如:
    char* c_str;c_str = str.data();c_str = str.data() + 5;// etc.
    // Write these 2 C-strings into the `std::string`'s underlying bufferstrcpy(str.data(), cstr1);strcpy(str.data() + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite the// first null terminator
    // print the stringstd::cout << str << "\n"; // output: `abcde fghijk`
  3. 技巧3[在C++11及更高版本中很好,但是很尴尬,所以不要这样做。它仅用于演示和学习目的]:使用#0方法获取第一个char的迭代器,然后使用迭代器的#1解引用方法获取迭代器的#2#3,然后获取其地址以获得#4。例如:
    char* c_str;c_str = &(*str.begin());c_str = &(*str.begin()) + 5;// etc.
    // Write these 2 C-strings into the `std::string`'s underlying bufferstrcpy(&(*str.begin()), cstr1);strcpy(&(*str.begin()) + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite// the first null// terminator
    // print the stringstd::cout << str << "\n"; // output: `abcde fghijk`

需要注意的重要一点是,当您调用str.resize(100)时,它会为基础字符串保留至少100个字节,将字符串的size()设置为100,并将所有100字符初始化为char()--AKA:charsize()2)的默认size()1值,即二进制零空终止符'\0'。因此,每当您调用str.size()时,即使字符串中只有"hello"后跟95个空终止符或零,它也会返回100。要在字符串中获取size()3或size()4的数量,您必须求助于C函数size()0,如下所示:

std::cout << strlen(str.c_str()) << "\n"; // prints `12` in the examples above
// instead of:std::cout << str.size() << "\n"; // prints `100` in the examples above

2.以只读、以null结尾的const char*访问std::string

要从std::string获得可读以空结尾的const char*,请使用#2方法。它返回一个C风格的字符串保证为空终止。请注意,#3方法不是一回事,因为它不能保证以空结尾!

示例:

std::string str = "hello world";printf("%s\n", str.c_str());

参考文献

  1. (关于Stack Overflow的问题)

    1. 如何将std::字符串转换为const char*或char*:如何将std::字符串转换为const char*或char*
    2. 直接写入std::字符串的char*缓冲区:直接写入std::字符串的char*缓冲区
    3. 有没有办法获取std: string的缓冲区:有没有办法获取std: string的缓冲区
  2. (我的内容)

    1. 【我的测试代码】string__use_std_string_as_a_c_str_buffer.cpp
    2. [我的Q]参见我问题底部的“相邻相关”部分:什么是调用'char()','uint8_t()','int64_t()',整数'T()'等,作为C++中的函数?
    3. *****+ [我关于在std::字符串中预先分配缓冲区的评论]:直接写入std::字符串的char*缓冲区
    4. *****+ [我对如何在std::字符串中预分配存储的评论,用作char*缓冲区]有没有办法获取std: string的缓冲区
  3. (来自cppreference.com社区wiki)

    1. https://en.cppreference.com/w/cpp/string/basic_string

      basic_string的元素连续存储,即basic_strings,&*(s.begin()+n)==&*s.begin()+n对于[0,s.size())中的任何n,或者等价地,指向s[0]的指针可以被传递给期望指向以null结尾的第一个元素的指针的函数(自C++11)CharT[]数组。

    2. https://en.cppreference.com/w/cpp/string/basic_string/operator_at

      返回对指定位置pos的字符的引用。不执行边界检查。如果pos>size(),则行为未定义。

    3. https://en.cppreference.com/w/cpp/string/basic_string/resize

    4. https://en.cppreference.com/w/cpp/string/basic_string/reserve

    5. https://en.cppreference.com/w/cpp/string/basic_string/data

    6. https://en.cppreference.com/w/cpp/string/basic_string/c_str

    7. https://en.cppreference.com/w/cpp/string/basic_string/clear