提问人:vengy 提问时间:6/21/2023 最后编辑:Benjamin Buchvengy 更新时间:6/21/2023 访问量:130
将 CRLF(回车符、换行符)连接到 std::string 的规则
Rules for concatenating a CRLF (Carriage Return, Line Feed) to a std::string
问:
下面的代码输出
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 之前的数据类型是否决定了串联规则?
答:
这个表达式:
"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>
在大多数情况下,字符串文本将转换为指向 () 的指针,因此任何进行加法(或类似)的尝试都会影响指针,而不是基础存储的数据,除非另一个操作数是(如)提供重载(或大小合适)的东西。const
char
std::string
pointer to const char
array of const char
事实上,您的第一个案例会导致指针算术。;-)
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::string
std::string
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 的用户定义文本运算符创建文本: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;
评论
clang
评论
"Content-Disposition: form-data;\r\n"