[英]Comparing against string literal not resolved at compile time
I recently found something akin to the following lines:我最近发现了类似于以下几行的内容:
#include <string>
// test if the extension is either .bar or .foo
bool test_extension(const std::string& ext) {
return ext == ".bar" || ".foo";
// it obviously should be
// return ext == ".bar" || ext == ".foo";
}
The function obviously does not do what the comment suggests.该功能显然没有按照评论的建议去做。 But that's not the point here.
但这不是重点。 Please note that this is not a duplicate of Can you use 2 or more OR conditions in an if statement?
请注意,这不是Can you use 2 or more OR conditions in an if statement? since I'm fully aware of how you would write the function properly!
因为我完全知道您将如何正确编写函数!
I started to wonder how a compiler might treat this snippet.我开始想知道编译器会如何处理这个片段。 My first intuition would have been that this would be compiled to
return true;
我的第一个直觉是这将被编译为
return true;
basically.基本上。 Plugging the example into godbolt , showed that neither GCC 9.2 nor clang 9 make this optimization with optimization
-O2
.将示例插入到Godbolt 中,表明 GCC 9.2 和 clang 9 都没有使用优化
-O2
进行此优化。
However, changing the code to 1但是,将代码更改为1
#include <string>
using namespace std::string_literals;
bool test_extension(const std::string& ext) {
return ext == ".bar"s || ".foo";
}
seems to do the trick since the assembly is now in essence:似乎可以解决问题,因为程序集现在本质上是:
mov eax, 1
ret
So my core question is: Is there something I missed that does not allow a compiler to make the same optimization on the first snippet?所以我的核心问题是:我是否遗漏了什么不允许编译器对第一个片段进行相同的优化?
1 With ".foo"s
this would not even compile, since the compiler does not want to convert a std::string
to bool
;-) 1使用
".foo"s
这甚至不会编译,因为编译器不想将std::string
转换为bool
;-)
Edit编辑
The following piece of code also gets "properly" optimized to return true;
下面这段代码也得到了“正确”优化以
return true;
: :
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
This will boggle your head even more: What happens if we create a custom char type MyCharT
and use it to make our own custom std::basic_string
?这会让你更加
MyCharT
:如果我们创建一个自定义 char 类型MyCharT
并使用它来创建我们自己的自定义std::basic_string
什么?
#include <string>
struct MyCharT {
char c;
bool operator==(const MyCharT& rhs) const {
return c == rhs.c;
}
bool operator<(const MyCharT& rhs) const {
return c < rhs.c;
}
};
typedef std::basic_string<MyCharT> my_string;
bool test_extension_custom(const my_string& ext) {
const MyCharT c[] = {'.','b','a','r', '\0'};
return ext == c || ".foo";
}
// Here's a similar implementation using regular
// std::string, for comparison
bool test_extension(const std::string& ext) {
const char c[] = ".bar";
return ext == c || ".foo";
}
Certainly, a custom type cannot be optimized more easily than a plain char
, right?当然,自定义类型不能比普通
char
更容易优化,对吗?
Here's the resulting assembly:这是生成的程序集:
test_extension_custom(std::__cxx11::basic_string<MyCharT, std::char_traits<MyCharT>, std::allocator<MyCharT> > const&):
mov eax, 1
ret
test_extension(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
sub rsp, 24
lea rsi, [rsp+11]
mov DWORD PTR [rsp+11], 1918984750
mov BYTE PTR [rsp+15], 0
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare(char const*) const
mov eax, 1
add rsp, 24
ret
So, what's the difference between my "custom" string type and std::string
?那么,我的“自定义”字符串类型和
std::string
之间有什么区别?
At least on GCC, Small String Optimization is actually compiled into the binary for libstdc++.至少在 GCC 上, Small String Optimization实际上被编译成 libstdc++ 的二进制文件。 This means that, during the compilation of your function, the compiler has no access to this implementation, thus, it cannot know if there are any side effects.
这意味着,在您的函数编译期间,编译器无法访问此实现,因此,它无法知道是否有任何副作用。 Because of this, it cannot optimize the call to
compare(char const*)
away.因此,它无法优化对
compare(char const*)
的调用。 Our "custom" class does not have this problem because SSO is implemented only for plain std::string
.我们的“自定义”类没有这个问题,因为 SSO 只为普通的
std::string
。
BTW, if you compile with -std=c++2a
, the compiler does optimize it away .顺便说一句,如果你用
-std=c++2a
编译,编译器会优化它。 I'm unfortunately not savvy enough on C++ 20 yet to know what changes made this possible.不幸的是,我对 C++ 20 还不够精明,还不知道是什么改变使这成为可能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.