C++ C+的NRVO+;字符串

C++ C+的NRVO+;字符串,c++,c++14,nrvo,C++,C++14,Nrvo,我试图找到一些关于名为返回值优化(NVRO)的std::string的信息。 我甚至不确定这是否适用,但我想知道从可读性和性能角度看,哪一个更好 std::string first(const bool condition) { std::string info = "This"; info += condition ? " is" : " irrelevant"; //.append() info += " info.";

我试图找到一些关于名为返回值优化(NVRO)的std::string的信息。 我甚至不确定这是否适用,但我想知道从可读性和性能角度看,哪一个更好

std::string first(const bool condition)
{
    std::string info = "This";
    info += condition 
        ? " is" 
        : " irrelevant";  //.append()

    info += " info.";

    return info; // nrvo here?
}

std::string second(const bool condition)
{
    const auto firstPart = "First part";
    const auto anotherPart = condition 
        ? " second part" 
        : " irrelevant ";  //.append()

    return std::string{}.append(firstPart).append(anotherPart);
}

std::string third(const bool condition)
{
    //would avoid due to poor readability if strings are long
    return std::string{}
        .append("First part")
        .append(condition ? " second" : "irrelevant");
}

int main()
{
    // printf("Hello World");
    const auto irrelevant {true};

    std::cout<<first(irrelevant)<<std::endl;
    std::cout<<second(irrelevant)<<std::endl;
    std::cout<<third(irrelevant)<<std::endl;

    return 0;
}
std::字符串优先(常量布尔条件)
{
std::string info=“This”;
信息+=条件
“是”
:“无关”;/.append()
信息+=“信息。”;
return info;//这里是nrvo吗?
}
标准::字符串秒(常量布尔条件)
{
const auto firstPart=“第一部分”;
const auto anotherPart=条件
“第二部分”
:“无关”;/.append()
返回std::string{}.append(第一部分).append(另一部分);
}
标准::第三个字符串(常量布尔条件)
{
//如果字符串很长,由于可读性差,将避免
返回std::字符串{}
.附加(“第一部分”)
.附加(条件?“第二条”:“不相关”);
}
int main()
{
//printf(“你好世界”);
常数自动无关{true};
标准::cout
  • 在C++11和14中,在这种情况下是允许的。从C++17中,返回值优化是强制性的(不再被视为复制省略)

  • 通过查看三个候选函数@我看不出这一点,但我并没有做太多汇编工作。不过这看起来可能更干净一些:


  • 您的第一个问题已由@Ted_Lyngom回答

    如果您真的对性能感到担忧(并且测量结果证明此函数是您的热点)
    std::string在这种情况下有点太重。它不允许所有编译时优化,例如
    constepr

    我建议使用
    std::string\u视图

    #include <string_view>
    
    constexpr std::string_view print(const bool condition) {
        if (condition){
            return "This is relevant info";
        } else {
            return "This is irrelevant info";
        }
    }
    
    int main() {
        std::string_view info = print(false);
        return info.size();
    }
    
    如果使用
    print(true)
    它将变为

    main:
            mov     eax, 21
            ret
    
    因此,如果您以后使用这个句子,编译器将对它进行最佳优化


    注:只有使用C++ 17编译器,否则,你只能使用。在这个地方编译器可以使用RVO。@ MigHalp这个问题仍然没有回答。没有任何建议的答案能起作用吗?谢谢,我的项目使用C++ 14,所以我猜“第二”。这将是最好的,但我认为这并不重要,因为这只是用于testing@MichałP.当然,您可以创建一个测试类,并查看您的C++14编译器如何处理它。它可能会省略复制,因为它被允许这样做。“在这种情况下允许省略复制”-我理解这是关于“第一”情况。“你当然可以创建一个测试类,看看你的C++14编译器是如何处理它的”-这也是关于“第一个”的吗?你能不能跟进一下“在C++11和14中,在这种情况下允许省略复制?”"-这是因为std::string impl吗?我不太熟悉复制省略,如果这个问题对您来说很愚蠢,那么很抱歉:)@MichałP。请将c++14标记添加到您的question@MichałP.这与
    string
    无关,因此如果您创建自己的类并在所有五个类中使用调试打印实现,您可以检查C++14的编译方式er在您的三个示例中都处理了它。我猜在第一个示例中,您将看到最少的复制/移动量。字符串连接的示例会是什么样子?抱歉,我没有明确提到它,但这与“条件”一起是我的“问题”:我需要根据传递给函数的参数创建一个字符串。您不能直接创建。请给出您的具体需求。如果您发现这确实是您的热点,并且您只有2*2选项,您可以使用
    string\u view
    对所有案例进行编码,如上所示。这将起作用,但不会增加可读性。如果您担心性能,首先分析整个程序,以确认担心是合理的。如果确实需要优化此代码,则在实际工作负载下、在实际平台上和使用实际编译器对其进行双向编码和分析。任何其他操作都是推测。您应使用
    sv
    后缀:
    “这是相关信息”sv
    因此长度信息可用于
    字符串视图
    构造函数
    main:
            mov     eax, 23
            ret
    
    main:
            mov     eax, 21
            ret