I want to write a template function that receives parameter by move or by copy. The most efficient way that I use is:
void setA(A a)
{
m_a = std::move(a);
}
Here, when we use is
A a;
setA(a); // <<---- one copy ctor & one move ctor
setA(std::move(a)); // <<---- two move ctors
I recently found out that defining it this way, with two functions:
void setA(A&& a)
{
m_a = std::move(a);
}
void setA(const A& a)
{
m_a = a; // of course we can so "m_a = std::move(a);" too, since it will do nothing
}
Will save a lot!
A a;
setA(a); // <<---- one copy ctor
setA(std::move(a)); // <<---- one move ctor
This is great! for one parameter... what is the best way to create a function with 10 parameters?!
void setAAndBAndCAndDAndEAndF...()
Any one has any ideas? Thanks!
In Java you should use getters and settersgetters and settersNoun. mutator (plural mutators) That which causes mutation or change. In object-oriented programming, the mutator function changes the value of the field that gives its name.https://en.wiktionary.org › wiki › mutatormutator - Wiktionary : It's considered a good practice because it encapsulates your object's inner state, therefore you can change the internals of the object and change the meaning of the value, doing complex things with it without changing its interface.
To achieve this, you must declare class variables/attributes as private (cannot be accessed from outside the class). If you want others to read or modify the value of a private member, you can provide public get and set methods.
The getter function is used to retrieve the variable value and the settersetterNoun. mutator (plural mutators) That which causes mutation or change. In object-oriented programming, the mutator function changes the value of the field that gives its name.https://en.wiktionary.org › wiki › mutatormutator - Wiktionary function is used to set the variable value. Remember: You can directly access public member variables, but private member variables are not accessible.
The two setter versions setA(A&& a)
and setA(const A& a)
can be combined into a single one using a forwarding reference (a.k.a. perfect forwarding):
template<typename A>
void setA(A&& a)
{
m_a = std::forward<A>(a);
}
The compiler will then synthesize either the rvalue- or lvalue-reference version as needed depending on the value category.
This also solves the issue of multi-value setters, as the right one will be synthesized depending on the value category of each parameter.
Having said that, keep in mind that setters are just regular functions; the object is technically already constructed by the time any setter can be called. In case of setA
, if A
has a non-trivial constructor, then an instance m_a
would already have been (default-)constructed and setA
would actually have to overwrite it.
That's why in modern C++, the focus is often not so much on move- vs. copy-, but on in-place construction vs. move/copy.
For example:
struct A {
A(int x) : m_x(x) {}
int m_x;
};
struct B {
template<typename T>
B(T&& a) : m_a(std::forward<T>(a)) {}
A m_a;
};
int main() {
B b{ 1 }; // zero copies/moves
}
The standard library also often offers "emplace"-style calls in addition to more traditional "push"/"add"-style calls. For example, vector::emplace
takes the arguments needed to construct an element, and constructs one inside the vector, without having to copy or move anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With