C++ 直接写入std::string的char*缓冲区
所以我有一个C++ 直接写入std::string的char*缓冲区,c++,string,c++14,language-lawyer,c++17,C++,String,C++14,Language Lawyer,C++17,所以我有一个std::string,还有一个函数,它接受char*并写入其中。由于std::string::c_str()和std::string::data()returnconst char*,我无法使用它们。所以我分配了一个临时缓冲区,用它调用一个函数并将它复制到std::string 现在我计划处理大量信息,复制这个缓冲区会产生明显的影响,我希望避免这种情况 有些人建议使用&str.front()或&str[0],但它会调用未定义的行为吗?C++98/03 不可能。字符串可以在写入时复制
std::string
,还有一个函数,它接受char*
并写入其中。由于std::string::c_str()
和std::string::data()
returnconst char*
,我无法使用它们。所以我分配了一个临时缓冲区,用它调用一个函数并将它复制到std::string
现在我计划处理大量信息,复制这个缓冲区会产生明显的影响,我希望避免这种情况
有些人建议使用&str.front()
或&str[0]
,但它会调用未定义的行为吗?C++98/03
不可能。字符串可以在写入时复制,因此它需要处理所有读写操作
C++11/14
在[string.require]中:
basic_string
对象中的类字符对象应连续存储。也就是说,对于任何basic\u字符串
对象
s
,标识&*(s.begin()+n)==&*s.begin()+n
应适用于n
的所有值,以便0可以简单地对非空字符串使用&s[0]
。这将为您提供一个指向缓冲区开始的指针
当您使用它将一个由n个字符组成的字符串放入其中时,字符串的长度(不仅仅是容量)需要至少提前为n,因为在不破坏数据的情况下,无法对其进行调整
也就是说,用法可以是这样的:
auto foo( int const n )
-> string
{
if( n <= 0 ) { return ""; }
string result( n, '#' ); // # is an arbitrary fill character.
int const n_stored = some_api_function( &result[0], n );
assert( n_stored <= n );
result.resize( n_stored );
return result;
}
auto foo(int const n)
->串
{
如果(n我不知道你打算用这个字符串做什么,但是如果
您所需要的只是一个字符缓冲区,它可以自动释放自己的内存,
然后我通常使用vector
或vector
或任何类型的
你需要多少缓冲
使用v
作为向量,可以保证&v[0]
指向
可以用作缓冲区的顺序内存。回答得好。只需添加一些内容:std::string
仅自C++11以来是一个连续内存容器。因此,仅自C++11以来,您就可以安全地使用&str[0]
(之前,它是特定于std lib实现的)在C++11之前,您必须使用一个临时的std::vector
并将其复制到std::string
中,或者使用它来实例化一个std::string
,因为操作符[]
的定义是“在哪里修改对象会导致未定义的行为”我认为你的答案是错误的。我认为这是标准中的一个缺陷。@Garf365:但实际上,没有一个标准库不为std::string
(自C++98以来)提供连续内存,所以它一直是安全的,C++11说它永远是安全的。@MartinBonner它说只有pos==size
。换句话说,你不能触摸终止符号。之前的一切都是公平的。我想我误解了操作符[]的定义
。未定义的行为仅适用于pos
不是的情况。C++17在std::string
中添加了非常量数据()
,但它仍然表示不能修改缓冲区。“哈?它在哪里这样说?在访问&std[0]
&str font()之前”
,…请确保有内存,即str.size()>0
。如果您刚刚实例化了str
,请使用str.resize()
@ildjam,看起来我完全看错了那篇文章。.data()
应该可以正常工作。std::string
也是如此,因为C++11及之前的版本,正如MatinBonner在其他答案的评论中所说,尽管这种行为是非标准的,但大多数标准库将std::string
实现为连续内存
auto foo( int const n )
-> string
{
if( n <= 0 ) { return ""; }
string result( n, '#' ); // # is an arbitrary fill character.
int const n_stored = some_api_function( &result[0], n );
assert( n_stored <= n );
result.resize( n_stored );
return result;
}