为什么将`const char [N]`和`const char *`传递给view :: c_str()会产生不同的二进制文件,而string_view会产生相同的结果吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么将`const char [N]`和`const char *`传递给view :: c_str()会产生不同的二进制文件,而string_view会产生相同的结果吗?相关的知识,希望对你有一定的参考价值。
使用std::string_view
,range::for_each
产生精确组装,const char[N]
和const char *
传递给std::string_view
ctor
换句话说,这段代码
auto str = "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
";
ranges::for_each(std::string_view{str}, std::putchar);
和
auto& str = "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
";
ranges::for_each(std::string_view{str}, std::putchar);
两者都低于汇编:
main: # @main
pushq %rbx
movq $-90, %rbx
.LBB0_1: # =>This Inner Loop Header: Depth=1
movsbl .L.str+90(%rbx), %edi
movq stdout(%rip), %rsi
callq _IO_putc
addq $1, %rbx
jne .LBB0_1
xorl %eax, %eax
popq %rbx
retq
.L.str:
.asciz "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
"
此外,如果我们将c字符串作为const char[N]
传递给ranges::view::c_str()
,
auto& str = "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
";
ranges::for_each(ranges::view::c_str(str), std::putchar);
这就产生了像std::string_view
产生的精确组装。
另一方面,如果我们将c字符串作为const char*
传递给ranges::view::c_str()
auto str = "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
";
ranges::for_each(ranges::view::c_str(str), std::putchar);
这次它产生一个不同的组件如下:
main: # @main
pushq %rbx
movb $116, %al
movq $-90, %rbx
.LBB0_1: # =>This Inner Loop Header: Depth=1
movsbl %al, %edi
movq stdout(%rip), %rsi
callq _IO_putc
movzbl .L.str+91(%rbx), %eax
incq %rbx
jne .LBB0_1
xorl %eax, %eax
popq %rbx
retq
.L.str:
.asciz "the quick brown fox is jumping on a lazy dog
the quick brown fox is jumping on a lazy dog
"
哪个组装胜利?
为什么std::string_view
决定产生相同的二进制文件?
view::c_str()
可以只用const char*
和const char [N]
产生一个更快的组装吗?
两个std::string_view
版本都调用相同的构造函数,它采用const char*
然后使用std::char_traits::length
(基本上是strlen
)来查找长度。编译器优化了strlen
,因为字符串文字对于编译器是可见的,因此它的长度是已知的,但是两种形式都使用完全相同的构造函数,并且两者都优化了strlen
,因此两者都生成相同的代码。
view::c_str
版本根据是给定指针还是数组使用不同的重载,请参阅https://github.com/ericniebler/range-v3/blob/1f4a96e9240786801e95a6c70afebf27f04cffeb/include/range/v3/view/c_str.hpp#L68
当给出一个指针时,它必须找到与使用strlen
类似的长度,但是当给定一个大小为N
的数组时,它使用N-1
作为长度。即使编译器将类似strlen
的代码优化为固定的编译时值,它仍然在编译不同的东西,因此生成的代码不相同并不奇怪。
以上是关于为什么将`const char [N]`和`const char *`传递给view :: c_str()会产生不同的二进制文件,而string_view会产生相同的结果吗?的主要内容,如果未能解决你的问题,请参考以下文章
将 Swift 字符串数组转换为 const char * const *
[转载] C++ string, const char*, char* 之间互相转换