现代编译器在使用构建器模式时是否使用复制省略

Does modern compilers use copy elision when using the builder pattern

我在我的代码库中使用了一些构建器模式,我想知道按值 return 是否应该比按引用 return 更受青睐,因为这是我所感受到的推动力现代 C++。在我看来,如果我按值应用 return 方法,该示例将生成大量副本。

class EmailBuilder
{
  public:
    EmailBuilder from(const string &from) {
        m_email.m_from = from;
        return *this;
    }
    
    EmailBuilder  to(const string &to) {
        m_email.m_to = to;
        return *this;
    }
    
    EmailBuilder  subject(const string &subject) {
        m_email.m_subject = subject;
        return *this;
    }
    
    EmailBuilder  body(const string &body) {
        m_email.m_body = body;
        return *this;
    }
    
    operator Email&&() {
        return std::move(m_email);  
    }
    
  private:
    Email m_email;
};

EmailBuilder Email::make()
{
    return EmailBuilder();
}

int main()
{
    Email mail = Email::make().from("me@mail.com")
                              .to("you@mail.com")
                              .subject("C++ builders")
                              .body("message");
                              

}

我的问题是编译器是否会优化此处生成的许多副本。如我所见,对于每个函数 class 我们都会生成构建器的新副本。

在许多情况下,按值返回受到青睐,因为它通常 side-steps life-time 问题。这不是其中一种情况,因为构建器的 life-time 通常定义明确且易于理解。因此,应优先考虑通过引用返回。

此外,在 C++20 中,您可以使用 designated initializers:

#include <string>

struct Email {
    std::string from    = "unknown";
    std::string to      = "unknown";
    std::string subject = "unknown";
    std::string body    = "unknown";
};

int main() {
    Email email = {
        .from   = "me@example.com",
        .to     = "you@example.com",
        .body   = "This is my email"
    };
}

(See online)

此处,主题为“未知”。