I am using a few builder patterns in my code base and I was wondering whether return by value should be favoured over the return by reference, given that is the push I am feeling with modern C . The example, in my opinion, would generate loads of copies if I applied the return by value approach.
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("[email protected]")
.to("[email protected]")
.subject("C builders")
.body("message");
}
My question is whether is if compilers would optimise the many copies generated here. As I see it, for each of the function class we generate a new copy of the builder.
CodePudding user response:
There are many cases where returning by value is favored since it typically side-steps life-time issue. This is not one of those cases because life-time of the builder is usually well defined and well understood. Thus returning by reference should be favored.
Also, in C 20 you can use 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 = "[email protected]",
.to = "[email protected]",
.body = "This is my email"
};
}
Here, subject is left "unknown".