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

9w11ddsr  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(196)

下面的代码输出

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;
}

我希望a有一个CRLF级联,但看起来它通过添加文本中\r (13) + \n (10) = 23起始偏移的ASCII值来执行指针运算。
然而,对于b,CRLF被正确地级联。
也许更好的方法是

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

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

问题

紧接在CRLF之前的数据类型是否确定串联规则?

j8ag8udp

j8ag8udp1#

这个表达式:

"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>生成一个字符串,该字符串连接到结尾。
在 * 大多数 * 情况下,字符串文字将转换为指向(constchar的指针,因此任何加法(或类似操作)的尝试都会影响指针,而不是底层存储的数据,除非其他操作数(如std::string)为pointer to const char(或正确大小的array of const char)提供重载。

sczxawaw

sczxawaw2#

事实上,你的第一个案例导致指针算术。;-)
对于C-String文字没有重载operator+。一个C-String字面量只是一个常量char s的数组,因此指针算法适用于它。

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

注意:char const(&)[32]是一个数组的引用,它包含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::string对象。std::string有一个overloaded plus operator,它被称为。它返回另一个std::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 's user defined literal operator创建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;

相关问题