现代编译器在使用构建器模式时是否使用复制省略
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"
};
}
此处,主题为“未知”。
我在我的代码库中使用了一些构建器模式,我想知道按值 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"
};
}
此处,主题为“未知”。