I want freeFunct to do non const stuff on its own copy of object a.
Let's say that freeFunct is required to be a free function
because in real code cases it takes many different parameters,
calls several public functions from all of them and there is no
point in making it a non-static member function of any class.
Three different ways of declaring it come to my mind.
I have the feeling that the third solution is the worse.
Is there any difference between the first two?
Is there something better?
void freeFunct1(A a){
a.doStuff();
}
void freeFunct2(const A& a){
A b = a;
b.doStuff();
}
/**users of freeFunct3 are expected
*to give a copy of their variable:
*{
* A b = a;
* freeFunct3(b);
*}
*/
void freeFunct3(A& a){
a.doStuff();
}
The first is best: it allows the caller to choose whether to copy or move his object, so can be more efficient if the caller doesn't need to keep a copy.
freeFunct1(a); // "a" is copied and not changed
freeFunct1(std::move(a)); // "a" is moved and perhaps changed
The second is similar, but forces a copy.
The third, as you say, is more error-prone, since the caller has to be aware that it will modify the argument.
First, as already said, don't do freeFunct3 if the semantics of the free function is to only modify its "own" object.
Second, there are differences between freeFunct1 and freeFunct2, relating to move optimization [C++11], exception safety, and potentially code size.
With freeFunct2 (taking by reference-to-const):
It will always construct a new copy of the argument, never move it [C++11].
If the copy construction of A throws an exception, it will throw inside the body of the function.
If A's copy constructor is inlined (and the function is not), it will be expanded once, inside the body of the function (even if the function is called from multiple different places).
With freeFunct1 (taking by value):
[C++11] You can avoid a copy if A has a move constructor and you pass an rvalue (e.g. call freeFunct1(A(args))).
If the copy (or move) construction of A throws an exception, it will throw at the call site.
If A's copy (or move) constructor is inlined, it will be expanded multiple times, at each call site.
Alternatively, you can overload on lvalue/rvalue reference to avoid unnecessarily copying rvalues:
void freeFunct4(const A& a){
A b = a;
b.doStuff();
}
void freeFunct4(A&& a){
a.doStuff();
}
IMO, the first is the best and the last is the worst.
Quite a few people, however, have gotten so accustomed to passing by const reference that they'll write #2 by default, even though in this case they need the copy that it's trying to avoid.
The first changes only the local copy. The second is the same as the first, but with extra code. The third will make changes to a visible to the caller of freeFunct3 as it's a non-const reference. If called as in the comment above the function, then it's no different than the second version really.
So if you just want to modify the local copy, without those changes being passed to the caller, then the first version is what I recommend.
Related
A have a few questions regarding copy elision and move.
Let's assume I have the following code:
class A {};
class B {
public:
A get1() const {
A local_var;
return local_var;
}
A get1bad() const {
A local_var;
return std::move(local_var);
}
A get2() const {
return member_var;
}
A get3() const {
return std::move(member_var);
}
private:
A member_var;
};
I read a lot of people saying to not do move on return.
From what I gather it's because with copy elision, on case get1, the compiler will not call constructor + move constructor but rather just one call to the default constructor, while case get1bad forces the compiler to call constructor + move.
My question is regarding cases where the variable is not local (get2 vs get3).
In that case, the variable is constructed anyway in the class. In get2 there's not really any optimization that I can see being possible. In this case, if I don't really care about ensuring class B has a valid A object, wouldn't it be better to actually move? Wouldn't it just call the move constructor which is generally cheaper than the copy constructor?
A get3() const {
return std::move(member_var);
}
You have a const function, so the member is also considered const and will not move anyway.
You could consider A get3() && to move the member when you have a temporary B. Maybe, if that happens often.
Having a getter that always destroys the class' value, even when it is an lvalue, seems like a rare use case.
I read a lot of people saying to not do move on return. From what I gather it's because with copy elision, on case get1, the compiler will not call constructor + move constructor but rather just one call to the default constructor, while case get1bad forces the compiler to call constructor + move.
If the operand to a return statement is just the name of a local variable, then std::move is basically implicitly applied. So at best return std::move(local_var); is redundant. This is a special rule for return. It doesn't apply elsewhere.
However, using return std::move(local_var); makes it so that the mandatory copy elision rules do not apply anymore, which is why it is not only redundant, but even worse than just return local_var;.
My question is regarding cases where the variable is not local (get2 vs get3). In that case, the variable is constructed anyway in the class. In get2 there's not really any optimization that I can see being possible. In this case, if I don't really care about ensuring class B has a valid A object, wouldn't it be better to actually move? Wouldn't it just call the move constructor which is generally cheaper than the copy constructor?
In your examples all member functions are const qualified. Therefore the type of std::move(member_var) will be const A&&. The move constructor takes a A&&, not const A&&. Therefore no move will happen and the copy constructor will be used for both get2 and get3's return values.
If you remove the const qualifiers, then yes return std::move(member_var); makes sense in that case and allows a move construction rather than copy construction. Copy/move elision is not possible in either case, since variable is not local to the function.
It is unlikely that you wouldn't care about the state of member_var after calling a member function, so it is unlikely that this will make sense in practice. If at all I would qualify the member function with &&, so that it is only used if the class instance is an rvalue, which is the only case I can think of where one doesn't care about the object state after the call to the member function.
In a small game I'm writing, I have a class Weapon with two constructors, one which takes in some parameters to produce a custom weapon, and one that grabs a default one (the CHAIN_GUN):
Weapon::Weapon (void) {
// Standard weapon
*this = getWeapon(CHAIN_GUN);
return;
}
Question: Are there any negative consequences from using *this and operator= to initialise a class?
Imagine that someone asked you to draw a painting... would you;
first draw your default (1st) (that familiar smilie face you like so much),
then draw what that someone asked for (2nd),
only to draw the same thing one more time, but on the canvas containing your default,
and then burn the 2nd painting?
This post will try to explain why this simile is relevant.
WHY IS IT A BAD IDEA?
I've never seen a default-constructor implemented with the use of the assignment-operator, and honestly it's not something that I'd recommend, nor support during a code review.
The major problem with such code is that we are, by definition, constructing two objects (instead of one) and calling a member-function, meaning that we construct all our members two times, and later having to copy/move initialize all members by calling the assignment operator.
It's unintuitive that upon requesting construction of 1 object, we construct 2 objects, only to later copy the values from the 2nd to the 1st and discard the 2nd.
Conclusion: Don't do it.
( Note: In a case where Weapon has base-classes it will be even worse )
( Note: Another potential danger is that the factory function accidentially uses the default-constructor, resulting in an infinite recursion not caught during compilation, as noted by #Ratchet Freat )
PROPOSED SOLUTION
In your specific case you are far better off using a default-argument in your constructor, as in the below example.
class Weapon {
public:
Weapon(WeaponType w_type = CHAIN_GUN);
...
}
Weapon w1; // w_type = CHAIN_GUN
Weapon w2 (KNOWLEDGE); // the most powerful weapon
( Note: An alternative to the above would be to use a delegating constructor, available in C++11 )
Using the assignment operator to implement a constructor is rarely a good idea. In your case, for example, you could just use a default parameter:
Weapon::Weapon(GunType g = CHAIN_GUN)
: // Initialize members based on g
{
}
In other cases, you might use a delegating constructor (with C++11 or later):
Weapon::Weapon(GunType g)
: // Initialize members based on g
{
}
Weapon::Weapon()
: Weapon(CHAIN_GUN) // Delegate to other constructor
{
}
One thing to keep in mind is that if operator= - or any function it calls - is virtual, the derived-class version won't be invoked. This could result in uninitialised fields and later Undefined Behaviour, but it all depends on your data members.
More generally, your bases and data members are guaranteed to have been initialised if they have constructors or appear in the initialiser list (or with C++11 are assigned to in the class declaration) - so apart from the virtual issue above, operator= will often work without Undefined Behaviour.
If a base or member has been initialised before operator=() is invoked, then the initial value is overwritten before it's used anyway, the optimiser may or may not be able to remove the first initialisation. For example:
std::string s_;
Q* p_;
int i_;
X(const X& rhs)
: p_(nullptr) // have to initialise as operator= will delete
{
// s_ is default initialised then assigned - optimiser may help
// i_ not initialised but if operator= sets without reading, all's good
*this = rhs;
}
As you can see, it's a bit error prone, and even if you get it right someone coming along later to update operator= might not check for a constructor (ab)using it....
You could end up with infinite recursion leading to stack overflow if getWeapon() uses the Prototype or Flyweight Patterns and tries to copy-construct the Weapon it returns.
Taking a step back, there's the question of why getWeapon(CHAIN_GUN); exists in that form. If we need a function that creates a weapon based on a weapon type, on the face of it a Weapon(Weapon_Type); constructor seems a reasonable option. That said, there are rare but plentiful edge cases where getWeapon might return something other than a Weapon object that can never-the-less be assigned to a Weapon, or might be kept separate for build/deployment reasons....
If you have defined a non-copy = assignment operator that lets the Weapon change its type after construction, then implementing the constructor in terms of assignment works just fine, and is a good way to centralize your initialization code. But if a Weapon is not meant to change type after construction, then a non-copy = assignment operator does not make much sense to have, let alone use for initialization.
I'm sure yes.
You already created object inside your "getWeapon" function, and then you copying it, that may be long operation. So, at least you have to try move semantic.
But.
If inside "getWeapon" you call to constructor (and you do, somehow "getWeapon" have to create your class to return it to your copy operation), you create very unclear architecture, when one constructor calls function that calls another constructor.
I believe you have to separate your parameters initialization to private functions, that have to be called from your constructors the way you want to.
struct TestConstRef {
std::string str;
Test(const std::string& mStr) : str{mStr} { }
};
struct TestMove {
std::string str;
Test(std::string mStr) : str{std::move(mStr)} { }
};
After watching GoingNative 2013, I understood that sink arguments should always be passed by value and moved with std::move. Is TestMove::ctor the correct way of applying this idiom? Is there any case where TestConstRef::ctor is better/more efficient?
What about trivial setters? Should I use the following idiom or pass a const std::string&?
struct TestSetter {
std::string str;
void setStr(std::string mStr) { str = std::move(str); }
};
The simple answer is: yes.
The reason is quite simple as well, if you store by value you might either need to move (from a temporary) or make a copy (from a l-value). Let us examine what happens in both situations, with both ways.
From a temporary
if you take the argument by const-ref, the temporary is bound to the const-ref and cannot be moved from again, thus you end up making a (useless) copy.
if you take the argument by value, the value is initialized from the temporary (moving), and then you yourself move from the argument, thus no copy is made.
One limitation: a class without an efficient move-constructor (such as std::array<T, N>) because then you did two copies instead of one.
From a l-value (or const temporary, but who would do that...)
if you take the argument by const-ref, nothing happens there, and then you copy it (cannot move from it), thus a single copy is made.
if you take the argument by value, you copy it in the argument and then move from it, thus a single copy is made.
One limitation: the same... classes for which moving is akin to copying.
So, the simple answer is that in most cases, by using a sink you avoid unnecessary copies (replacing them by moves).
The single limitation is classes for which the move constructor is as expensive (or near as expensive) as the copy constructor; in which case having two moves instead of one copy is "worst". Thankfully, such classes are rare (arrays are one case).
A bit late, as this question already has an accepted answer, but anyways... here's an alternative:
struct Test {
std::string str;
Test(std::string&& mStr) : str{std::move(mStr)} { } // 1
Test(const std::string& mStr) : str{mStr} { } // 2
};
Why would that be better? Consider the two cases:
From a temporary (case // 1)
Only one move-constructor is called for str.
From an l-value (case // 2)
Only one copy-constructor is called for str.
It probably can't get any better than that.
But wait, there is more:
No additional code is generated on the caller's side! The calling of the copy- or move-constructor (which might be inlined or not) can now live in the implementation of the called function (here: Test::Test) and therefore only a single copy of that code is required. If you use by-value parameter passing, the caller is responsible for producing the object that is passed to the function. This might add up in large projects and I try to avoid it if possible.
I searched how to implement + operator properly all over the internet and all the results i found do the following steps :
const MyClass MyClass::operator+(const MyClass &other) const
{
MyClass result = *this; // Make a copy of myself. Same as MyClass result(*this);
result += other; // Use += to add other to the copy.
return result; // All done!
}
I have few questions about this "process" :
Isn't that stupid to implement + operator this way, it calls the assignment operator(which copies the class) in the first line and then the copy constructor in the return (which also copies the class , due to the fact that the return is by value, so it destroys the first copy and creates a new one.. which is frankly not really smart ... )
When i write a=b+c, the b+c part creates a new copy of the class, then the 'a=' part copies the copy to himself.
who deletes the copy that b+c created ?
Is there a better way to implement + operator without coping the class twice, and also without any memory issues ?
thanks in advance
That's effectively not an assignment operator, but a copy constructor. An operation like addition creates a new value, after all, so it has to be created somewhere. This is more efficient than it seems, since the compiler is free to do Return Value Optimization, which means it can construct the value directly where it will next be used.
The result is declared as a local variable, and hence goes away with the function call - except if RVO (see above) is used, in which case it was never actually created in the function, but in the caller.
Not really; this method is much more efficient than it looks at first.
Under the circumstances, I'd probably consider something like:
MyClass MyClass::operator+(MyClass other) {
other += *this;
return other;
}
Dave Abrahams wrote an article a while back explaining how this works and why this kind of code is usually quite efficient even though it initially seems like it shouldn't be.
Edit (thank you MSalters): Yes, this does assume/depend upon the commutative property holding for MyClass. If a+b != b+a, then the original code is what you want (most of the same reasoning applies).
it calls the assignment operator(which copies the class) in the first line
No, this is copy-initialization (through constructor).
then the copy constructor in the return (which also copies the class
Compilers can (and typically do) elide this copy using NRVO.
When i write a=b+c, the b+c part creates a new copy of the class, then the 'a=' part copies the copy to himself. who deletes the copy that b+c created
The compiler, as any other temporary value. They are deleted at the end of full-expression (in this case, it means at or after ; at the end of line.
Is there a better way to implement + operator without coping the class twice, and also without any memory issues ?
Not really. It's not that inefficient.
This appears to be the correct way to implement operator+. A few points:
MyClass result = *this does not use the assignment operator, it should be calling the copy constructor, as if it were written MyClass result(*this).
The returned value when used in a = b + c is called a temporary, and the compiler is responsible for deleting it (which will probably happen at the end of the statement ie. the semicolon, after everything else has been done). You don't have to worry about that, the compiler will always clean up temporaries.
There's no better way, you need the copy. The compiler, however, is allowed to optimise away the temporary copies, so not as many as you think may be made. In C++0x though, you can use move constructors to improve performance by transfering ownership of the content of a temporary rather than copying it in its entirity.
I'll try my best to answer:
Point (1): No, it does not call the assignment operator. Instead it calls a constructor. Since you need to construct the object anyway (since operator+ returns a copy), this does not introduce extra operations.
Point (2): The temporary result is created in stack and hence does not introduce memory problem (it is destroyed when function exits). On return, a temporary is created so that an assignment (or copy constructor) can be used to assign the results to a (in a=b+c;) even after result is destroyed. This temporary is destroyed automatically by the compiler.
Point (3): The above is what the standard prescribes. Remember that compiler implementors are allowed to optimize the implementation as long as the effect is the same as what the standard prescribed. I believe, compilers in reality optimize away many of the copying that occurs here. Using the idiom above is readable and is not actually inefficient.
P.S. I sometime prefer to implement operator+ as a non-member to leverage implicit conversion for both sides of the operators (only if it makes sense).
There are no memory issues (provided that the assignment operator, and copy constructor are well written). Simply because all the memory for these objects is taken on the stack and managed by the compiler. Furthermore, compilers do optimize this and perform all the operations directly on the final a instead of copying twice.
This is the proper way of implementing the operator+ in C++. Most of the copies you are so afraid of will get elided by the compiler and will be subject to move semantics in C++0x.
The class is a temporary and will be deleted. If you bind the temporary to a const& the life time of the temporary will be extended to the life time of the const reference.
May implementing it as a freefunction is a little more obvious. The first parameter in MyClass::operator+ is an implicit this and the compiler will rewrite the function to operator+(const MyClass&, const MyClass&) anyway.
As far as I remember, Stroustrup's 'The C++ Programming Language' recommends to implement operators as member functions only when internal representation is affected by operation and as external functions when not. operator+ does not need to access internal representation if implemented based on operator+=, which does.
So you would have:
class MyClass
{
public:
MyClass& operator+=(const MyClass &other)
{
// Implementation
return *this;
}
};
MyClass operator+(const MyClass &op1, const MyClass &op2)
{
MyClass r = op1;
return r += op2;
}
Is there a difference between foo and bar:
class A
{
Object __o;
void foo(Object& o)
{
__o = o;
}
void bar(Object o)
{
__o = o;
}
}
As I understand it, foo performs no copy operation on object o when it is called, and one copy operation for assignment. Bar performs one copy operation on object o when it is called and another one for assignment. So I can more or less say that foo uses 2 times less memory than bar (if o is big enough). Is that correct ?
Is it possible that the compiler optimises the bar function to perform only one copy operation on o ? i.e. makes __o pointing on the local copy of argument o instead of creating a new copy?
It depends. For example, if the compiler decides to inline the function, obviously there will be no copy since there is no function call.
If you want to be sure, pass by const-reference:
void bar(const Object& o)
This makes no copies. Note your non-const version requires an lvalue, because the reference is mutable. foo(Object()) wouldn't work, but temporaries (rvalues) can be bound to a const-reference.
Double-underscores in identifiers are reserved for the compiler, by the way.
Since assignment typically takes const Something& as a parameter, it would be canonical to write:
void foo(const Object& o)
{
__o = o;
}
But this does not answer your question about the optimization. I'm not sure that, in general, such optimization can / will be made by the compiler.
I think its fair to say that foo() performs one less copy than bar(). Its not very meaningful to say how much more or less memory is consumed, because for simple objects they are stored on the stack and cleaned up after return from bar().
As has been said, don't use underscores at the start of identifiers.
I think compilers can do the optimization in case of temporary objects. This technique is called copy elision.
Please refer to the answers to question i had posted what-is-copy-elision-and-how-it-optimizes-copy-and-swap-idiom. This ans is really helpful What is copy elision and how does it optimize the copy-and-swap idiom?
Though i am not an expert in this, from what i understand compliers can optimize copying of temporary object in some scenarios.
For example if your code is called like this
bar(getObject())
where getObject has a signature
Object getObject()
This call will result in creation of a temporary of type Object. If the compiler does not do any optimization that temporay has to be copied into the argument to bar.
However if compiler supports copy elision this copying wont be performed and the temporary will be passed as an argument to bar function. So the copy is avoided and its performance is same as foo which accepts a reference. But as i said it happens only in case of temporary object