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

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

下面的代码输出

  1. rm-data;
  2. Content-Disposition: form-data;

https://godbolt.org/z/h5z89qv6f

  1. #include <iostream>
  2. #include <string>
  3. int main()
  4. {
  5. std::string a = "Content-Disposition: form-data;" + '\r' + '\n';
  6. std::cout << a << std::endl;
  7. std::string b = "Content-Disposition: " + std::string("form-data;") + '\r' + '\n';
  8. std::cout << b << std::endl;
  9. }

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

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

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

问题

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

j8ag8udp

j8ag8udp1#

这个表达式:

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

...在类型方面是:<string literal> + <char> + <char>。这是不直接支持的,所以它寻找一个转换,将允许它工作,并提出了<char *> + <integer> + <integer>
因此,我们最终会得到一个指向字符串字面量中间(或超过末尾)的指针。
这个表达式:

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

...在类型方面是:

  1. <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的数组,因此指针算法适用于它。

  1. operator+(
  2. operator+(
  3. char const(&)[32]
  4. , char
  5. ) -> char const*
  6. , char
  7. ) -> char const*

注意:char const(&)[32]是一个数组的引用,它包含32个常数char的元素。您可以使用以下命令进行测试:

  1. #include <type_traits>
  2. static_assert(std::is_same_v<
  3. decltype("Content-Disposition: form-data;"),
  4. char const(&)[32]
  5. >);
  6. static_assert(std::is_same_v<
  7. decltype("Content-Disposition: form-data;" + '\n'),
  8. char const*
  9. >);

在第二个例子中,第一个加号操作涉及到一个std::string对象。std::string有一个overloaded plus operator,它被称为。它返回另一个std::string对象,所以下面的加号再次调用这些重载中的一个。

  1. operator+(
  2. operator+(
  3. operator+(
  4. char const(&)[22]
  5. , std::string
  6. ) -> std::string
  7. , char
  8. ) -> std::string
  9. , char
  10. ) -> std::string

clang给出了有关代码的适当警告:

  1. <source>:7:59: warning: adding 'char' to a string does not append to the string [-Wstring-plus-int]
  2. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  3. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
  4. <source>:7:59: note: use array indexing to silence this warning
  5. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  6. ^
  7. & [ ]
  8. <source>:7:59: warning: adding 'char' to a string pointer does not append to the string [-Wstring-plus-char]
  9. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  10. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
  11. <source>:7:59: note: use array indexing to silence this warning
  12. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  13. ^
  14. & [ ]
  15. <source>:7:66: warning: adding 'char' to a string pointer does not append to the string [-Wstring-plus-char]
  16. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  17. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
  18. <source>:7:66: note: use array indexing to silence this warning
  19. std::string fieldA{ "Content-Disposition: form-data;" + '\r' + '\n'};
  20. ^
  21. & [ ]
  22. 3 warnings generated.

https://godbolt.org/z/rhTs1W777
使用std::string 's user defined literal operator创建std::string文字:

  1. #include <iostream>
  2. #include <string>
  3. int main()
  4. {
  5. using namespace std::literals; // ""s -> std::string
  6. auto const c = "Content-Disposition: form-data;"s + '\r' + '\n';
  7. std::cout << c << std::endl;
  8. }

输出:

  1. Content-Disposition: form-data;
展开查看全部

相关问题