这个 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