将 CRLF(回车符、换行符)连接到 std::string 的规则

Rules for concatenating a CRLF (Carriage Return, Line Feed) to a std::string

提问人:vengy 提问时间:6/21/2023 最后编辑:Benjamin Buchvengy 更新时间:6/21/2023 访问量:130

问:

下面的代码输出

rm-data;
Content-Disposition: form-data;

https://godbolt.org/z/h5z89qv6f

#include <iostream>
#include <string>

int main()
{
    std::string a = "Content-Disposition: form-data;" + '\r' + '\n';
    std::cout << a << std::endl;

    std::string b = "Content-Disposition: " + std::string("form-data;") + '\r' + '\n';
    std::cout << b << std::endl;
}

我希望有一个 CRLF 连接起来,但看起来它通过在文本中添加起始偏移量的 ASCII 值来执行指针算术。a\r (13) + \n (10) = 23

但是,对于 ,CRLF 是正确连接的。b

也许更好的方法是

std::string a = "Content-Disposition: form-data;" + std::string("\r\n");

std::string a = "Content-Disposition: form-data;\r\n";

问题

紧挨着 CRLF 之前的数据类型是否决定了串联规则?

c++ 字符串文字 stdstring

评论

2赞 john 6/21/2023
没有串联规则,而是有使用哪个版本的 operator+ 的规则。这些规则取决于运算符的左侧和右侧的类型。你是对的,字符串文字 + char 版本是指针算术。
3赞 463035818_is_not_an_ai 6/21/2023
为什么不呢?"Content-Disposition: form-data;\r\n"

答:

7赞 Jerry Coffin 6/21/2023 #1

这个表达式:

"Content-Disposition: form-data;" + '\r' + '\n'

...就类型而言是:。这不直接支持,因此它寻找允许它工作的转换,并提出 .<string literal> + <char> + <char><char *> + <integer> + <integer>

因此,我们最终会得到一个指向字符串文本中间(或末尾)的指针。

这个表达式:

"Content-Disposition: " + std::string("form-data;") + '\r' + '\n'

...就类型而言是:

<string literal> + <string> + <char> + <char>

同样,这是从左到右完成的,所以我们从 开始。这没有直接支持,但确实如此,所以这就是它的作用(产生结果)。这导致了 ,它直接被支持(并且再次返回一个 )。然后又是同样的事情。正如您所料,生成一个字符串,该字符连接到末尾。<string literal> + <string><char *> + <string><string><string> + <char><string><string> + <char>

在大多数情况下,字符串文本将转换为指向 () 的指针,因此任何进行加法(或类似)的尝试都会影响指针,而不是基础存储的数据,除非另一个操作数是(如)提供重载(或大小合适)的东西。constcharstd::stringpointer to const chararray of const char

2赞 Benjamin Buch 6/21/2023 #2

事实上,您的第一个案例会导致指针算术。;-)

C-String 文本没有重载。C-String 文字只是一个常量 s 的数组,因此指针算术适用于它。operator+char

operator+(
    operator+(
        char const(&)[32]
        , char
    ) -> char const*
    , char
) -> char const*

注意:是对具有 32 个常量元素的数组的引用。您可以使用以下方法进行测试:char const(&)[32]char

#include <type_traits>

static_assert(std::is_same_v<
    decltype("Content-Disposition: form-data;"),
    char const(&)[32]
>);

static_assert(std::is_same_v<
    decltype("Content-Disposition: form-data;" + '\n'),
    char const*
>);

在第二种情况下,是第一个加号运算中涉及的对象。 有一个重载的加号运算符,它被调用。它返回另一个对象,因此下面再次调用其中一个重载。std::stringstd::stringstd::string

operator+(
    operator+(
        operator+(
            char const(&)[22]
            , std::string
          ) -> std::string
        , char
    ) -> std::string
    , char
) -> std::string

clang提供有关代码的相应警告:

<source>:7:59: warning: adding 'char' to a string does not append to the string [-Wstring-plus-int]
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
<source>:7:59: note: use array indexing to silence this warning
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                                                          ^
                        &                                 [     ]
<source>:7:59: warning: adding 'char' to a string pointer does not append to the string [-Wstring-plus-char]
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
<source>:7:59: note: use array indexing to silence this warning
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                                                          ^
                        &                                 [     ]
<source>:7:66: warning: adding 'char' to a string pointer does not append to the string [-Wstring-plus-char]
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
<source>:7:66: note: use array indexing to silence this warning
    std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
                                                                 ^
                        &                                        [     ]
3 warnings generated.

https://godbolt.org/z/rhTs1W777

使用 std::string 的用户定义文本运算符创建文本:std::string

#include <iostream>
#include <string>

int main()
{
    using namespace std::literals; // ""s -> std::string

    auto const c = "Content-Disposition: form-data;"s + '\r' + '\n';
    std::cout << c << std::endl;
}

输出:

Content-Disposition: form-data;

评论

0赞 vengy 6/21/2023
关于警告的好说明。gcc 或 VS 编译器没有任何警告。谢谢!clang