提问人:Tony The Lion 提问时间:4/12/2011 最后编辑:sbiTony The Lion 更新时间:4/15/2011 访问量:1926
将 C 函数的 std::string 转换为 char* 时要注意什么?
What to watch out for when converting a std::string to a char* for C function?
问:
我读过很多帖子,询问如何将 C++ 转换为 a 以将其传递给 C 函数的问题,似乎有很多关于这样做的警告。必须注意字符串是连续的,还有很多其他事情。关键是我从来没有真正理解过一个人需要注意的所有要点,为什么?std::string
const std::string&
char*
我想知道是否有人可以总结一下从 a 到 a 的转换,这是传递给 C 函数所必需的?std::string
char*
当 是引用并且它只是非常量引用时,以及 C 函数何时更改 以及何时不会更改它时,就会出现这种情况。std::string
const
char*
答:
当 C 函数不改变 后面的字符串时,您可以同时用于 const 和非 const 实例。理想情况下,它应该是一个 ,但如果不是(因为遗留的 API),您可以合法地使用 .
但是,只要您不修改字符串,您就只能使用 From 中的指针!char*
std::string::c_str()
std::string
const char*
const_cast
c_str()
当 C 函数确实更改了 后面的字符串时,您唯一安全且可移植的使用方法是自己将其复制到临时缓冲区(例如从 )!确保事后释放临时内存 -- 或使用 ,这保证具有连续内存。char*
std::string
c_str()
std::vector
基本上,有三点很重要:
根据仍然有效的标准,实际上并不能保证使用连续存储(据我所知,这是由于更改)。但事实上,所有当前的实现都可能使用连续存储。出于这个原因,(和)实际上可能会在内部创建字符串的副本......
std::string
c_str()
data()
(和 ) 返回的指针仅在未调用原始字符串上的非常量方法时有效。这使得当 C 函数挂在指针上时(而不是仅在实际函数调用期间使用它)时,它就不合适了。
c_str()
data()
如果字符串有可能被修改,那么从字符串中抛弃恒定性不是一个好主意。您必须使用字符串的副本创建一个缓冲区,并将其传递给 C 函数。如果创建缓冲区,请记住添加 null 终止。
c_str()
评论
c_str()
必须是恒定时间,所以不能复制。但是允许一直保留单独的副本,所以你的第二点仍然成立。
.c_str()
.c_str()
.c_str()
首先,const reference 还是 value 不会改变任何内容。
然后,您必须考虑函数的期望。那里
是函数可以对 或
a --- 的原始版本,用于
例如,使用了这些类型,并且可能仍然有
这样的代码。希望它是罕见的,在以下方面,
我假设 C 函数中的 引用终止的字符串。char*
char const*
memcpy
char*
'\0'
如果 C 函数采用 ,则可以将
的结果 ;如果它需要一个 ,它
取决于。如果它只需要一个,因为它的日期来自
C的前几天,事实上,它什么也没修饰,后面跟着一个是
适当。如果 C 函数使用 作为输出
参数,但是,事情变得更加困难。我个人
首选声明一个缓冲区,传递它,然后
将结果转换为 ,但都是已知的
使用连续缓冲区的实现,以及
该标准的下一个版本将需要它,所以正确
对第一个(使用 ,然后传递,然后
将字符串重新调整为生成的长度(已确定
使用,如有必要)也可以使用。char const*
std::string::c_str()
char*
char*
const
std::string::c_str()
const_cast
char*
char[]
std::string
std::string
std::string
std::string::resize()
&s[0]
strlen(s.c_str())
最后(但对于使用 C 程序来说,这也是一个问题),您必须考虑任何生存期问题。最
函数采用或简单地使用
指针,并忘记它,但如果函数保存指针
在某个地方,为了以后使用,字符串对象必须至少存在
只要,在此期间不应修改其大小。
(同样,在这种情况下,我更喜欢使用 .char[]
char*
char const*
char[]
评论
&s[0]
s
std:string 可以存储零个字节。这意味着当传递给 C 函数时,它可能会过早被截断,因为 C 函数将在第一个零字节处停止。例如,如果您尝试使用 C 函数来过滤或转义不需要的字符,这可能会产生安全隐患。
std::string::c_str() 的结果有时会因更改字符串的操作(非常量成员函数)而失效。如果在首次使用 c_str() 然后修改字符串后尝试使用此指针,则诊断错误(“Heisenbugs”)将非常困难。
永远不要使用。 就不那么麻烦了。
const_cast
goto
评论
goto
const_cast
const_cast
goto
[我会添加一条评论,但我没有足够的代表,所以很抱歉添加(尚未)另一个答案。
虽然当前标准确实不能保证 std::string 的内部缓冲区是连续的,但似乎几乎所有实现都使用连续缓冲区。此外,新的 C++0x 标准(即将获得 ISO 批准)要求在 std::string 中使用连续的内部缓冲区,甚至当前的 C++03 标准也要求在调用 data() 或 &str[0] 时返回连续缓冲区(尽管它不一定是以 null 结尾的)。有关详细信息,请参阅此处。
不过,这仍然不能使写入字符串变得安全,因为该标准不会强制实现在调用 data()、c_str() 或运算符时实际返回其内部缓冲区,并且也不会阻止它们使用写入时复制等优化,这可能会使事情进一步复杂化(看来新的 C++0x 将禁止写入时复制)。话虽如此,如果你不关心最大的可移植性,你可以检查你的目标实现,看看它在里面实际做了什么。AFAIK,Visual C++ 2008/2010 总是返回真正的内部缓冲区指针,并且不执行写入时复制(它确实具有小字符串优化,但这可能不是问题)。
评论
&str[0]
data()
const char*
operator[]
char&
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
评论