简体   繁体   English

与编译时未解析的字符串文字进行比较

[英]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

See it live!现场看!


脑洞大开!

So, what's the difference between my "custom" string type and std::string ?那么,我的“自定义”字符串类型和std::string之间有什么区别?

Small String Optimization小字符串优化

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM