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


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

你可以使用&mystring[0]来获得一个char *指针,但是有几个问题:你不一定会得到一个以0结尾的字符串,你也不能改变字符串的大小。特别要注意的是,不要添加超过字符串结尾的字符,否则会导致缓冲区溢出(并可能导致崩溃)。

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

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


如果你只是想将std::string传递给一个需要const char *的函数,你可以使用.c_str():

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

如果你需要一个非const char *,调用.data():

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

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

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

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

指针指向一个以空结束的字符串,终止符不计入str.size()。不允许将非空字符分配给结束符。


鉴于说…

std::string x = "hello";

从string对象中获取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++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对象允许包含任意数量的NULs——std::string对它们没有特殊处理(c++ 03中相同)。

在c++ 03中,事情要复杂得多(重点区别突出显示):

x.data() returns const char* to the string's internal buffer which wasn't required by the Standard to conclude with a NUL (i.e. might be ['h', 'e', 'l', 'l', 'o'] followed by uninitialised or garbage values, with accidental accesses thereto having undefined behaviour). x.size() characters are safe to read, i.e. x[0] through x[x.size() - 1] for empty strings, you're guaranteed some non-NULL pointer to which 0 can be safely added (hurray!), but you shouldn't dereference that pointer. &x[0] for empty strings this has undefined behaviour (21.3.4) e.g. given f(const char* p, size_t n) { if (n == 0) return; ...whatever... } you mustn't call f(&x[0], x.size()); when x.empty() - just use f(x.data(), ...). otherwise, as per x.data() but: for non-const x this yields a non-const char* pointer; you can overwrite string content x.c_str() returns const char* to an ASCIIZ (NUL-terminated) representation of the value (i.e. ['h', 'e', 'l', 'l', 'o', '\0']). although few if any implementations chose to do so, the C++03 Standard was worded to allow the string implementation the freedom to create a distinct NUL-terminated buffer on the fly, from the potentially non-NUL terminated buffer "exposed" by x.data() and &x[0] x.size() + 1 characters are safe to read. guaranteed safe even for empty strings (['\0']).

访问外部法律索引的后果

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

这些指针什么时候失效?

如果调用某个字符串成员函数来修改字符串或保留进一步的容量,则上述任何方法之前返回的任何指针值都将无效。您可以再次使用这些方法来获取另一个指针。(规则与迭代器到字符串的规则相同)。

请参见如何在x离开作用域或在....下面进一步修改后仍使字符指针有效

那么,用哪个更好呢?

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

在c++ 03中,使用.c_str(),除非确定.data()是足够的,并且优先使用.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(),但人们有时不会这样做,因为:

using .data() communicates to other programmers reading the source code that the data is not ASCIIZ (rather, you're using the string to store a block of data (which sometimes isn't even really textual)), or that you're passing it to another function that treats it as a block of "binary" data. This can be a crucial insight in ensuring that other programmers' code changes continue to handle the data properly. C++03 only: there's a slight chance that your string implementation will need to do some extra memory allocation and/or data copying in order to prepare the NUL terminated buffer

作为进一步的提示,如果函数的形参需要(const) char*,但不坚持获取x.s size(),则该函数可能需要一个ascii输入,因此.c_str()是一个很好的选择(函数需要知道文本以某种方式在何处结束,因此如果它不是一个单独的形参,则只能是一个约定,如长度前缀或哨兵或一些固定的预期长度)。

如何得到一个字符指针有效,即使x离开范围或进一步修改

你需要将字符串x的内容复制到x外部的一个新的内存区域。这个外部缓冲区可能在很多地方,比如另一个字符串或字符数组变量,由于在不同的作用域(例如命名空间,全局,静态,堆,共享内存,内存映射文件),它可能有或没有与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*的其他原因

那么,上面你已经看到了如何获取(const) char*,以及如何独立于原始字符串复制文本,但是你可以用它做什么呢?一些随机的例子……

give "C" code access to the C++ string's text, as in printf("x is '%s'", x.c_str()); copy x's text to a buffer specified by your function's caller (e.g. strncpy(callers_buffer, callers_buffer_size, x.c_str())), or volatile memory used for device I/O (e.g. for (const char* p = x.c_str(); *p; ++p) *p_device = *p;) append x's text to an character array already containing some ASCIIZ text (e.g. strcat(other_buffer, x.c_str())) - be careful not to overrun the buffer (in many situations you may need to use strncat) return a const char* or char* from a function (perhaps for historical reasons - client's using your existing API - or for C compatibility you don't want to return a std::string, but do want to copy your string's data somewhere for the caller) be careful not to return a pointer that may be dereferenced by the caller after a local string variable to which that pointer pointed has left scope some projects with shared objects compiled/linked for different std::string implementations (e.g. STLport and compiler-native) may pass data as ASCIIZ to avoid conflicts


我正在使用一个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 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不可复制)。


看看这个:

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模板的概要,添加了非const重载data():

图表*数据()noexcept; 返回:一个指针p,对于[0,size()]中的每个i, p + i == &运算符。


CharT const * from std::basic_string<CharT>

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

从std::basic_string<图表>

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

C++11

CharT const * from std::basic_string<CharT>

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

从std::basic_string<图表>

从c++ 11开始,标准说:

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(). 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. 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();

Pro

简单而简短 快速(唯一不涉及复制的方法)

Cons

Final '\0'不会被改变/不一定是非const内存的一部分。

2. 使用std::向量<图>

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

Pro

简单的 自动内存处理 动态

Cons

需要字符串复制

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

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

Pro

简单的 堆栈内存处理

Cons

静态 需要字符串复制

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

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

Cons

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

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

Pro

最大的“控制”

Con

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


试试这个

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

比方说, 字符串str =“堆栈”;

1)将字符串转换为char*

  char* s_rw=&str[0]; 

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

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

   const char* s_r=&str[0];

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


从c++ std字符串转换到c风格字符串现在真的很容易。

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

字符串::连续复制函数形参

Char字符串指针 字符串大小,b复制多少个字符 位置,从字符复制开始的位置

另一件重要的事,

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

代码考试在下面

// char string
char chText[20];

// c++ string
string text =  "I am a Programmer";

// conversion from c++ string to char string
// this function does not append a null character at the end of operation
text.copy(chText, text.size(), 0);

// we need to put it manually
chText[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 constructor
string text(chText);

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

// char string
char chText[20] = "I am a Programmer";

// c++ string
string text;

// convertion from char string to c++ string
// using assign function
text.assign(chText);

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

// char string
char chText[20] = "I am a Programmer";

// c++ string
// convertion from char string to c++ string using assignment operator overloading
string text = chText;

第三个也可以写成如下-

// char string
char chText[20] = "I am a Programmer";

// c++ string
string text;


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

这在将std::string的底层char*缓冲区传递给C调用时特别有用,这些调用期望并写入char*缓冲区。这样你可以两全其美!: c++ std::string的优点,以及它与你从c++调用的C库的直接可用性。

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

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

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

下面的所有用法都需要c++ 11或更高版本,除了char* data()调用,它需要c++ 17或更高版本。

要运行和测试下面所有示例代码,请查看并运行eRCaGuy_hello_world repo中的string__use_std_string_as_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 is
str.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 chars
c_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()`

简介:

如果有急事,你需要:

底层缓冲区的可读写char* C-string:只需使用下面代码示例中的技术1部分:char* c_str1 = &str[i];。 只要确保首先通过str.resize(BUFFER_SIZE)预先分配底层缓冲区大小(如果需要的话),就可以确保底层缓冲区足够大以满足您的需要。 底层缓冲区的只读const char* C-string:使用与上面相同的方法(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 is
str.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_at
char* 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/data
char* c_str11 = str.data();      // same as c_str1 above
char* c_str12 = str.data() + 10; // same as c_str2 above
char* 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/RandomAccessIterator
char* c_str21 = &(*str.begin());      // same as c_str1 and c_str11 above
char* c_str22 = &(*str.begin()) + 10; // same as c_str2 and c_str12 above
char* 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 above
const char* const_c_str2 = str.c_str() + 10; // a const version of c_str2 above
const char* const_c_str3 = str.c_str() + 33; // a const version of c_str3 above

注意,你也可以使用.at(i)和.front() std::string方法,但我不会深入讨论这些方法,因为我认为我的例子已经足够了。有关它们的文档,请参见:

https://en.cppreference.com/w/cpp/string/basic_string/at 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()是不够的!std::string::operator[]的cppreference.com社区wiki页面正确地声明:

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

resize()方法改变的是大小,而不是reserve()方法,后者只改变capacity()。

Ex:

#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 size
std::cout << "str.size() = " << str.size() << "\n";

对于下面的所有例子,假设你有这些c字串:

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

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

Technique 1 [best option if using C++11]: array indexing using operator[] to obtain a char, followed by obtaining its address with &. Ex: char* c_str; c_str = &str[0]; c_str = &str[5]; // etc. // Write these 2 C-strings into a `std::string`'s underlying buffer strcpy(&str[0], cstr1); strcpy(&str[sizeof(cstr1) - 1], cstr2); // `- 1` to overwrite the first // null terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk` What if you have a pointer to a std::string? If you have a ptr to a std::string, it must be dereferenced first with *pstr before you can index into it as an array with the operator[] as &(*pstr)[0], so the syntax above becomes a little more awkward. Here is a full example: 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]); Technique 2 [best option if using C++17]: use the .data() method to obtain a char* directly. Ex: char* c_str; c_str = str.data(); c_str = str.data() + 5; // etc. // Write these 2 C-strings into the `std::string`'s underlying buffer strcpy(str.data(), cstr1); strcpy(str.data() + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite the // first null terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk` Technique 3 [fine in C++11 and 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*. Ex: char* c_str; c_str = &(*str.begin()); c_str = &(*str.begin()) + 5; // etc. // Write these 2 C-strings into the `std::string`'s underlying buffer strcpy(&(*str.begin()), cstr1); strcpy(&(*str.begin()) + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite // the first null // terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk`

Something important to be aware of is that when you call str.resize(100), it reserves at least 100 bytes for the underlying string, sets the size() of the string to 100, and initializes all 100 of those chars to char()--AKA: the default value initialization value for char (see my question here), which is the binary zero null-terminator, '\0'. Therefore, whenever you call str.size() it will return 100 even if the string simply has "hello" in it followed by 95 null-terminators, or zeros. To get the length, or number of non-null-terminators in the string, you'll have to resort to the C function strlen(), like this:

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. 将std::string作为只读的、以null结尾的const char*访问

要从std::string中获得一个可读的以null结尾的const char*,请使用.c_str()方法。它返回一个c风格的字符串,保证以空结束。注意.data()方法不是一回事,因为它不能保证以空结束!

例子:

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

参考文献

(questions on Stack Overflow) How to convert a std::string to const char* or char*: How to convert a std::string to const char* or char* Directly write into char* buffer of std::string: Directly write into char* buffer of std::string Is there a way to get std:string's buffer: Is there a way to get std:string's buffer (my content) [my test code] string__use_std_string_as_a_c_str_buffer.cpp [my Q] See the "Adjacently related" section at the bottom of my question here: What is a call to `char()`, `uint8_t()`, `int64_t()`, integer `T()`, etc, as a function in C++? *****+ [my comments about pre-allocating a buffer in the std::string]: Directly write into char* buffer of std::string *****+ [my comment on how to pre-allocate storage in a std::string, to be used as a char* buffer] Is there a way to get std:string's buffer (from the cppreference.com community wiki) https://en.cppreference.com/w/cpp/string/basic_string: The elements of a basic_string are stored contiguously, that is, for a basic_string s, &*(s.begin () + n) == &*s.begin() + n for any n in [0, s.size()), or, equivalently, a pointer to s[0] can be passed to functions that expect a pointer to the first element of a null-terminated (since C++11)CharT[] array. https://en.cppreference.com/w/cpp/string/basic_string/operator_at Returns a reference to the character at specified location pos. No bounds checking is performed. If pos > size(), the behavior is undefined. https://en.cppreference.com/w/cpp/string/basic_string/resize https://en.cppreference.com/w/cpp/string/basic_string/reserve https://en.cppreference.com/w/cpp/string/basic_string/data https://en.cppreference.com/w/cpp/string/basic_string/c_str https://en.cppreference.com/w/cpp/string/basic_string/clear