I must have a fundamental misunderstanding about C++11. My professors told me it wasn't possible to pass a non-primitive type to a function except by reference or pointer. However, the following code works just fine
#include <iostream>
using namespace std;
class MyClass
{
public:
int field1;
};
void print_string(string s) {
cout << s << endl;
}
void print_myclass(MyClass c) {
cout << c.field1 << endl;
}
int main(int argc, char *argv[])
{
string mystr("this is my string");
print_string(mystr); // works
MyClass m;
m.field1=9;
print_myclass(m);
return 0;
}
Running the program yields the following output
this is my string
9
RUN SUCCESSFUL (total time: 67ms)
I'm using MinGW/g++ on Win7
Why does that work? I thought non-primitive types couldn't be passed by value?!
Non-primitive types can certainly be passed by value. (This is covered in section 5.2.2 [expr.call]
of the C++ Standard.)
However, there are a few reasons why this is often discouraged, especially in C++03 code.
First, for large objects, it is less efficient to do so (when compared with passing by reference), as the data is passed on the stack. A reference will take one word on the stack, so passing any object via the stack which is larger than one word will necessarily be slower.
Second, passing by value invokes the copy constructor (or, as @templatetypedef points out, potentially the move constructor in C++11). This additional processing could incur a certain amount of overhead.
Third, you may have intended to modify the passed in object, but by passing in a copy (by value), any changes you make within the function will not affect the original object. So it is important to get the semantics correct (ie. whether or not you want to modify the original). Hence this is a potential bug in some circumstances.
Finally, if there is a poorly written class with no copy constructor or assignment operator, the compiler will automatically generate a default one for you. This will perform a shallow copy, which could cause problems such as memory leaks. This is yet another good reason why it is very important to implement these special methods. Full details are in this article:
In general for C++03 code, you would normally pass by a const&
reference if you don't intend to modify the object, or by normal &
reference if you need to modify the object. Use a pointer if the parameter is optional.
Some good answers and discussion are also found in these questions, especially the discussion on move semantics:
A complete answer for C++11 is more complicated:
Probably the best summary of which approach to use:
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