有时您需要用 C 函数构造的字符填充 std::string
。一个典型的例子是这样的:
constexpr static BUFFERSIZE{256};
char buffer[BUFFERSIZE];
snprint (buffer, BUFFERSIZE, formatstring, value1, value2);
return std::string(buffer);
注意我们首先需要填充本地缓冲区,然后将其复制到 std::string
。
如果计算了最大缓冲区大小并且不一定要存储在堆栈中的内容,则该示例会变得更加复杂。例如:
constexpr static BUFFERSIZE{256};
if (calculatedBufferSize>BUFFERSIZE)
{
auto ptr = std::make_unique<char[]>(calculatedBufferSize);
snprint (ptr.get(), calculatedBufferSize, formatstring, value1, value2);
return std::string(ptr.get());
}
else
{
char buffer[BUFFERSIZE];
snprint (buffer, BUFFERSIZE, formatstring, value1, value2);
return std::string(buffer);
}
这使得代码更加复杂,如果计算出的 BufferSize 大于我们在堆栈上想要的大小,我们基本上会执行以下操作:
- 分配内存(make_unique)
- 用想要的结果填满内存
- 分配内存(std::string)
- 复制内存到字符串
- 释放内存
因为 C++17 std::string
有一个非常量 data()
方法,暗示这是操作字符串的方式。所以这样做似乎很诱人:
std::string result;
result.resize(calculatedBufferSize);
snprint (result.data(), calculatedBufferSize, formatstring, value1, value2);
result.resize(strlen(result.c_str()));
return result;
我的实验表明,需要最后一次调整大小才能确保正确报告字符串的长度。 std::string::length()
不搜索空终止符,它只返回大小(就像 std::vector
一样)。
请注意,我们进行的分配和复制要少得多:
- 分配内存(调整字符串大小)
- 用想要的结果填满内存
老实说,虽然它看起来效率更高,但在我看来它也很“不标准”。有人可以指出这是否是 C++17 标准允许的行为吗?还是有另一种方法可以更有效地进行这种操作?
请不要引用问题Manipulating std::string ,因为这个问题是关于更肮脏的逻辑(甚至使用 memset
)。
也不要回答我必须使用 C++ 流(std::string_stream
,高效?老实说?)。有时您只是想重用 C 语言中的高效逻辑。
最佳答案
修改 data()
指向的内容是可以的,假设您没有将 data() + size()
的值设置为 null 以外的任何值特点。来自 [string.accessors] :
charT* data() noexcept;
Returns: A pointer
p
such thatp + i == addressof(operator[](i))
for eachi
in[0, size()]
.Complexity: Constant time.
Remarks: The program shall not modify the value stored at
p + size()
to any value other thancharT()
; otherwise, the behavior is undefined.
result.resize(strlen(result.c_str()));
语句看起来确实有点奇怪。 std::snprintf
返回写入的字符数;使用该值来调整字符串的大小会更合适。此外,构造具有正确大小的字符串而不是构造一个立即调整大小的空字符串看起来更整洁:
std::string result(maxlen, '\0');
result.resize(std::max(0, std::snprintf(result.data(), maxlen, fmt, value1, value2)));
return result;
关于c++ - 使用 C 函数操作 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54106346/