这个 std::string 构造函数在做什么?
What is this std::string constructor doing?
我正在尝试用 C++ 为 WebExtension 浏览器插件编写本机主机客户端。
我找了例子,可惜只找到了几个。
有this simple good looking one I'm following但是我不明白构造字符串的部分如下:
json get_message() {
char raw_length[4];
fread(raw_length, 4, sizeof(char), stdin);
uint32_t message_length = *reinterpret_cast<uint32_t*>(raw_length);
if(!message_length)
exit(EXIT_SUCCESS);
char message[message_length];
fread(message, message_length, sizeof(char), stdin);
string m( message, message + sizeof message / sizeof message[0] );
return json::parse(m);
}
我查看了 C++ std::string 构造函数的多个文档,但我无法弄清楚这里到底发生了什么。
string m( message, message + sizeof message / sizeof message[0] );
是做什么的?
为什么不直接做 string m(message)
?
还有 char message[message_length];
行让我感到困惑,因为 message_length
不是常量,但显然这是 GCC 特定的功能。
What does string m( message, message + sizeof message / sizeof message[0] );
do?
message
衰减为指向第一个元素的指针,sizeof message / sizeof message[0]
是数组中元素的数量,message + sizeof message / sizeof message[0]
是指向数组末尾的指针。请注意,这是获取元素数量的不必要的复杂方法。我建议改用 message + message_length
。
构造函数复制这些迭代器(指针)之间范围内的所有字符。迭代器跨越整个数组。
What I don't understand is I can't seem to find a std::string constructor that accepts (char*, char*)
构造函数看起来像这样(简化):
template<class InputIt>
string(InputIt first, InputIt last);
从参数中推导出模板参数为char*
。
And why not just do string m(message)
?
该构造函数要求 message
以空字符终止。如果参数不是由空字符终止的,那么程序的行为将是未定义的。那可就糟了。
此外,如果数组确实包含空终止符,则该构造函数不会将它们复制到字符串中,而迭代器范围构造函数会这样做。如果打算复制空终止符,那将很糟糕。
There is also the char message[message_length];
line which confused me because message_length
is not a constant
这在 C++ 中是不允许的。节目是ill-formed.
由于示例质量较差,这里提供一个修复主要问题的版本:
json get_message(std::istream& in)
{
std::uint32_t message_length;
// NOTE input is assumed to be in native byte order
in.read(reinterpret_cast<char*>(&message_length), sizeof message_length);
if (!in)
throw std::runtime_error("Invalid message length");
if (!message_length)
throw std::runtime_error("No input");
std::string m('[=11=]', message_length);
in.read(m.data(), message_length);
if (!in)
throw std::runtime_error("Invalid message");
return json::parse(m);
}
如果您想使用其他错误处理而不是异常,您可以进行调整。演示的错误处理有改进的空间(唯一异常 类 等)。
与原始示例的最大差异是该函数可以从任何输入流中读取;不仅是标准输入。我选择这样做不仅因为它更通用,而且因为实际上没有标准+可移植的方式来从标准输入读取二进制文件。参见 C read binary stdin
我正在尝试用 C++ 为 WebExtension 浏览器插件编写本机主机客户端。
我找了例子,可惜只找到了几个。
有this simple good looking one I'm following但是我不明白构造字符串的部分如下:
json get_message() {
char raw_length[4];
fread(raw_length, 4, sizeof(char), stdin);
uint32_t message_length = *reinterpret_cast<uint32_t*>(raw_length);
if(!message_length)
exit(EXIT_SUCCESS);
char message[message_length];
fread(message, message_length, sizeof(char), stdin);
string m( message, message + sizeof message / sizeof message[0] );
return json::parse(m);
}
我查看了 C++ std::string 构造函数的多个文档,但我无法弄清楚这里到底发生了什么。
string m( message, message + sizeof message / sizeof message[0] );
是做什么的?
为什么不直接做 string m(message)
?
还有 char message[message_length];
行让我感到困惑,因为 message_length
不是常量,但显然这是 GCC 特定的功能。
What does
string m( message, message + sizeof message / sizeof message[0] );
do?
message
衰减为指向第一个元素的指针,sizeof message / sizeof message[0]
是数组中元素的数量,message + sizeof message / sizeof message[0]
是指向数组末尾的指针。请注意,这是获取元素数量的不必要的复杂方法。我建议改用 message + message_length
。
构造函数复制这些迭代器(指针)之间范围内的所有字符。迭代器跨越整个数组。
What I don't understand is I can't seem to find a std::string constructor that accepts (char*, char*)
构造函数看起来像这样(简化):
template<class InputIt>
string(InputIt first, InputIt last);
从参数中推导出模板参数为char*
。
And why not just do
string m(message)
?
该构造函数要求 message
以空字符终止。如果参数不是由空字符终止的,那么程序的行为将是未定义的。那可就糟了。
此外,如果数组确实包含空终止符,则该构造函数不会将它们复制到字符串中,而迭代器范围构造函数会这样做。如果打算复制空终止符,那将很糟糕。
There is also the
char message[message_length];
line which confused mebecause message_length
is not a constant
这在 C++ 中是不允许的。节目是ill-formed.
由于示例质量较差,这里提供一个修复主要问题的版本:
json get_message(std::istream& in)
{
std::uint32_t message_length;
// NOTE input is assumed to be in native byte order
in.read(reinterpret_cast<char*>(&message_length), sizeof message_length);
if (!in)
throw std::runtime_error("Invalid message length");
if (!message_length)
throw std::runtime_error("No input");
std::string m('[=11=]', message_length);
in.read(m.data(), message_length);
if (!in)
throw std::runtime_error("Invalid message");
return json::parse(m);
}
如果您想使用其他错误处理而不是异常,您可以进行调整。演示的错误处理有改进的空间(唯一异常 类 等)。
与原始示例的最大差异是该函数可以从任何输入流中读取;不仅是标准输入。我选择这样做不仅因为它更通用,而且因为实际上没有标准+可移植的方式来从标准输入读取二进制文件。参见 C read binary stdin