使用 &front() 修改 std::string 中的基础字符数组
Using &front() to modify underlying character array in std::string
我必须在我的一个程序中与 C 库接口,并且我正在编写一个薄包装器以使用C++类型,例如 std::string
.有相当多的函数接受char*
和最大长度作为参数,并用以零结尾的 C 字符串覆盖char*
指向的内存。传统上,我使用堆栈数组并手动将数据复制到字符串中。
std::string call_C_function(int x) {
char buf[MAX_LEN] = {0}; // MAX_LEN is defined by the library
size_t len = MAX_LEN;
C_function(x, buf, &len);
return std::string(buf, len);
}
我试图避免复制并想出一个解决方案,但我不知道这是否严格合法:
std::string call_C_function(int x) {
std::string buf(MAX_LEN, ' '); // MAX_LEN is defined by the library
size_t len = MAX_LEN;
C_function(x, &buf.front(), &len);
buf.resize(len);
return buf;
}
这可以编译和工作,但我有疑问,因为std::string
类使得很难获得指向字符数据的非常量指针。 c_str()
和 data()
都返回常量指针。该标准明确禁止修改这些函数的缓冲区:
21.4.7.1: 程序不得更改字符数组中存储的任何值。
从文档中看,这似乎是合法的,因为front()
返回对缓冲区第一个字符的引用,该字符必须是连续的(我使用的是 C++11/14(。在 21.4.5 中,front()
的语义是根据不禁止修改的operator[](0)
定义的。
从语言标准的角度来看,这种方法有什么问题吗?这似乎是一个漏洞,允许在 21.4.7.1 中明确禁止修改。
很好。不允许通过从 const
成员函数返回的指针修改字符串,但这并不意味着根本不允许修改字符串。您有一个非常量字符串,因此您可以对其进行修改。原则上,这与做s[0] = 'a'; s[1] = 'b';
等没有什么不同。
禁止覆盖字符串数据之后存储的最终' '
,但我从您的示例中假设MAX_LEN
包含由 C 函数写入的 null 终止符的空间,因此 C 函数只会覆盖字符串内容,而不会覆盖之后存储的额外字符。
有一个未解决的问题(LWG 2391(建议添加一个等同于&s.front()
的非常量std::string::data()
,并且可以让您直接访问,而不会让您担心违背图书馆的意图。
我对C++11的阅读:
const charT& front(( const;
字符和前线((;
需要: !空((
效果:等效于运算符 [](0(。
让我们看看运算符[]:
const_reference运算符[](size_type pos( const;
引用运算符[](size_type pos(;
1 要求:pos <= size((。
2 返回:*(begin(( + pos( 如果 pos
由于您预先分配了缓冲区,因此pos
将小于 size((。 begin(( 返回一个迭代器,因此所有常用的迭代器特征都适用。
所以,根据我对C++11的解释,这种方法应该是合法的。
- 指向指向字符数组的指针数组的指针
- 比较字符数组
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 使用无符号字符数组有效存储内存
- 按字符值访问int数组
- 错误:字符数组的初始值设定项太多
- 对字符数组中的元素执行逐位操作
- C++,在int数组中输入字符串或字符会输出0,而不是ascii或error
- C++ 无法在字符数组中使用 for 循环打印字母模式
- 如何在 C++ 中从文件中读取字符数组(带有一些空格)
- 移动二维数组中的字符
- C++ 传递二维字符数组
- 无法在 C++ 中输入字符数组
- C++ 带结构的数组字符
- 数组字符包含量超出预期
- 读取文件并添加到数组字符
- 如何在Qt中更改或替换数组字符
- 为什么编译器不在参数中传递数组字符 *arr[] 的大小?
- 井字棋数组字符错误
- 分割数组字符