tags:

views:

244

answers:

8

Hello. Coming from c#, where classes instances are passed by reference(this is, a copy of the reference is passed when you call a function, instead of the integral value), I'd like to know how this works in c++. In the following case, _poly = poly; is copying the value of poly to _poly, or what? Thanks

#include <iostream>
#include <stdio.h>
#include <stdarg.h>
#include <vector>
using namespace std;

class polynomial {
private:
    vector<int> _poly;
public:
    void Set(vector<int> poly);
};

void polynomial::Set(vector<int> poly) {
    _poly = poly;                             <----------------
}
+2  A: 

This will copy the entire vector. Assignment is by value in C++. If you are assigning a pointer, the pointer value is assigned. References may not be reassigned to refer to another object once initialized, so assignment of them alters the referent object.

Fred Larson
+2  A: 

The copy operator for vectors will copy the contents of the vector over.

Soo Wei Tan
+3  A: 

This will do a shallow-copy of the vector of ints. This will generally work as you would expect (_poly will end up containing the same values as poly).

You would see some strange behaivor if you had pointers (as they would be copied by value).

In general, you would want to pass that parameter by const reference:

void polynomial::Set( const vector<int>& poly )

In this case, passing by const reference will not affect the outcome and will be more efficient since it will eliminate an unneeded copy of the vector being passed into the method.

Jesse
Probably worth mentioning that with ints, shallow copy and deep copy are the same thing.
Rob Kennedy
And that shallow and deep copy are not commonly used terms in C++
anon
@Rob Kennedy, good point.
Jesse
@Neil Butterworth, I think shallow/deep copy are pretty commonly used - particularly in the context of the assignment operator when the class has members that are pointers to objects.
Jesse
+12  A: 

poly's values will be copied into _poly -- but you will have made an extra copy in the process. A better way to do it is to pass by const reference:

void polynomial::Set(const vector<int>& poly) {
    _poly = poly;                      
}

EDIT I mentioned in comments about copy-and-swap. Another way to implement what you want is

void polynomial::Set(vector<int> poly) { 
    _poly.swap(poly); 
}

This gives you the additional benefit of having the strong exception guarantee instead of the basic guarantee. In some cases the code might be faster, too, but I see this as more of a bonus. The only thing is that this code might be called "harder to read", since one has to realize that there's an implicit copy.

rlbond
From an exception safety point of view, you could also use copy-and-swap, but you are a beginner and that's an advanced technique.
rlbond
Smart compilers will be able to pass by reference if the object isn't modified.
Georg
@gs: but why rely on that? Better to explicitly note the semantics of one's call. And, in debug mode, the spurious copy will not be averted.
rlbond
@gs: really? I don't think so, to note whether the function modifies or not the passed object the compiler must see the function internals. Now, when compiling other compilations units, only the signature is present, and the compiler cannot know what the internal function makes of the passed element. I don't think compilers can perform that optimization, can you provide a pointer here?
David Rodríguez - dribeas
Copy-and-swap (void polynomial::Set(vector<int> poly) { _poly.swap(poly); }) could avoid another copy that is in the above version if the argument was a temporary. It's generally the way I write it.
Todd Gardner
A: 

Yes, the line you point to is copying the entire vector. Furthermore, there will be a copy on the function call, as well, since that's not const.

Basically, if the vector has any size to it, this is VERY expensive.

Michael Kohne
A: 

Unless you assign or pass a parameter by reference (using the & prefix) you are passing by value. For classes, this means that a copy of the object is constructed using either a supplied or implicitly generated (shallow) copy constructor for the type. This can be expensive - and is often undesirable.

In your example, the vector is copied twice - once when it is passed as a parameter to the Set() method, and again when it is assigned to the _poly member.

You could avoid the first copy by passing the vector by reference:

void polynomial::Set(const vector<int>& poly) // passes the original parameter by reference
{
    _poly = poly; // still makes a copy
}
LBushkin
+2  A: 

There are three possibilities:

Pass by value

void someFunction(SomeClass theObject);

Pass a pointer

void someFunction(SomeClass *theObject);

Pass by reference

void someFunction(SomeClass &theObject);
Georg
You should mention that the pointer/ref methods should when at all possible be const. It is common for those new to c++ to leave out the const, and in turn we can no longer guarantee that the input remains unchanged.
DeusAduro
+1  A: 

Your vector will be copied.

What's actually going on is that the "=" operator of vector has been overloaded to do the actual copy.