强制转换 c_str() 仅适用于短字符串
Casting c_str() only works for short strings
我在C++中使用了一个 C 库并编写了一个包装器。有一次我需要将std::string
转换为 c 样式字符串。有一个带有函数的类,它返回一个字符串。如果字符串较短,则强制转换返回的字符串有效,否则无效。下面是一个简单且简化的示例来说明该问题:
#include <iostream>
#include <string>
class StringBox {
public:
std::string getString() const { return text_; }
StringBox(std::string text) : text_(text){};
private:
std::string text_;
};
int main(int argc, char **argv) {
const unsigned char *castString = NULL;
std::string someString = "I am a loooooooooooooooooong string"; // Won't work
// std::string someString = "hello"; // This one works
StringBox box(someString);
castString = (const unsigned char *)box.getString().c_str();
std::cout << "castString: " << castString << std::endl;
return 0;
}
执行上面的文件会将其打印到控制台:
castString:
而如果我交换someString
上的注释,它会正确打印
投线:你好
这怎么可能?
您正在对由 getString()
成员函数重新调整的临时字符串对象调用c_str
。c_str()
返回的指针仅在原始字符串对象存在时才有效,因此在您分配castString
的行的末尾,它最终会成为悬空指针。正式地,这会导致未定义的行为。
那么为什么这对短字符串有效呢?我怀疑您看到了短字符串优化的效果,这是一种优化,对于小于特定长度的字符串,字符数据存储在字符串对象本身的字节内而不是堆中。返回的临时字符串可能存储在堆栈上,因此在清理它时未发生解除分配,指向过期字符串对象的指针仍保存旧的字符串字节。这似乎与你所看到的一致,但它仍然不意味着你正在做的事情是一个好主意。:-)
box.getString()
是一个 匿名的临时。 c_str()
仅对变量的长度有效。
因此,在您的情况下,c_str()
在您到达std::cout
时无效。读取指针内容的行为未定义。
(有趣的是,由于std::string
以不同的方式存储短字符串,短字符串的行为可能会有所不同。
按值返回时
box.getString()
是暂时的,所以
box.getString().c_str()
仅在表达式期间有效,那么它是一个悬空指针。
你可以用
const std::string& getString() const { return text_; }
box.getString()
生成一个临时的。调用 c_str()
会给你一个指向临时的指针。在临时不复存在后,即立即,指针无效,一个悬空的指针。
使用悬空指针是未定义的行为。
首先,你的代码具有与字符串长度无关的 UB:
在castString = (const unsigned char *)box.getString().c_str();
getString
返回的字符串被销毁,castString
是指向已销毁字符串对象的内部缓冲区的悬空指针。
您的代码"工作"小字符串的原因可能是小字符串优化:短字符串(通常)保存在字符串对象本身中,而不是保存在动态分配的数组中,显然该内存在您的情况下仍然可以访问且未修改。
- OpenGL - 在 NDC 中计算位置适用于着色器,但不适用于'regular'程序
- 使用模板参数重载C++方法:如何使其适用于模板的子类?
- 如何修复我的最大公约数代码?它适用于除零和零以外的所有数字
- 选择排序C++(已修改)并非适用于所有情况
- 无法让"std::enable_if"适用于无作用域枚举
- 请找出我的代码中的错误,它在提交得到错误答案的同时仍然适用于我的所有测试用例
- 确定夏令时是否适用于特定日期
- 是否有一种 STL 算法可以最后找到,但它也适用于指针?
- QT 样式表主题,适用于使用属性选择器的整个应用程序
- C++带有适用于左值和右值的引用参数的函数
- 代码适用于调试,但不适用于发布
- 为什么哈希<常量字符*>适用于字符串而不是字符串变量?
- 如何在 C++ 中安全地为 char *array 重新分配内存(它适用于自定义字符串类)
- 为什么 fstream.open(文件名) 适用于文字而不是生成的字符串?
- 适用于短文件名的最佳字符串哈希函数
- 强制转换 c_str() 仅适用于短字符串
- C++:二叉搜索树适用于整数,但当我尝试传递字符串时崩溃
- CopyFile 不适用于环境字符串,但仅适用于放置文件的标准目录。无论如何要克服这个?
- 从字符串中删除重复字符的函数仅适用于相邻字符
- 中的方法<cstring>也适用于字符串类吗?