transferring parameters in C++ - c++

can I have this snippet of the code:
C *pa1 = new C(c2);
and I transfer it to another function:
foo(pa1);
what exactly do I transfer actual pointer or its copy, thanks in advance
and can somebody give some info about in which cases info is copied, and in which I transfer actual pointer
declaration of foo:
foo(A const *pa)

Assuming foo is declared as:
void foo(C* p);
you are passing a copy of the pointer.
This means, if foo does this:
p = &some_other_object;
that change to the pointer won't be seen by the caller.
It also means we're copying the pointer, not the thing pointed to. If foo does this:
p->bar = "Smurf!"
pa1 in the caller will also see the change. For this reason, pointers are often used to implement a kind of pass-by-reference.
If foo were declared:
void foo(C*& p);
then p would be a reference to pa1, and changes to p would result in changes to pa1. Historically, this has also been implemented using pointers to pointers:
void foo(C** p);
in which case you call foo like this:
foo(&pa1);
and foo can do something like:
*p = &some_other_object;
to change what pa1 points to.

Since pa1 is of type pointer-to-C, you are passing a pointer to C to the function foo. You are not copying the actual object.
To pass an object, you would need foo to take an object of type C and to dereference pa1 when passing it:
void foo(C);
...
foo(*pa1);

Since pa1 is a pointer (as you have defined it as a C *), you are passing a pointer to the C object into foo.
That said, whether you are passing the pointer by value or by reference is unknown without seeing the declaration of foo.

C *pa1;
object of type 'C*' is created on the stack (local variable pa1)
pa1 = new C(c2);
object of type 'C' is created on the heap, its address is returned into 'pa1' variable
foo(pa1)
We can say "object of type 'C*' (variable pa1) is passed by-value to function foo, the function gets a copy of the pointer",
But also "object of type 'C' (this one created on the heap) passed by-reference (through pointer) to function foo, no copy 'C' object is made.
To pass by-reference (without making a copy of an object) either c++ reference to the object can be used or pointer to the object. They act similar when going about function parameter passing, i.e all of 4 lines below gives the same effect, passing by-reference (these are const references, remove const keyword to be able to permanently modify the object by the foo function):
foo(const A *pa) { pa->DoSth(); } /*...*/ foo(some_pointer);
foo(const A *pa) { pa->DoSth(); } /*...*/ foo(&some_reference);
foo(const A &pa) { pa.DoSth(); } /*...*/ foo(*some_pointer);
foo(const A &pa) { pa.DoSth(); } /*...*/ foo(some_reference);

Related

Force non-null while preserving constness

Consider this class
class Foo
{
public:
Foo()
: r_obj(&nullobj)
{}
void setDataRef(const T& obj)
{
r_obj = &obj;
}
private:
static T nullobj;
const T* r_obj;
};
This forces r_obj to point to something, and I know that the class cannot modify the logical state of whatever it points to. However, now it is perfectly legal to pass a temporary object to setDataRef which is really bad.
If instead using setDataRef(T&), the constness is lost.
Passing a pointer does not force the object to really point to something.
Is it possible to get all three:
Constness
Non-null
Forbid temporary
In old C++ I think this was impossible, but with C++11 we can do:
class Foo
{
public:
Foo()
: r_obj(&nullobj)
{}
void setDataRef(const T& obj)
{
r_obj = &obj;
}
void setDataRef(T&& obj) = delete; // Crucial extra line
private:
static T nullobj;
const T* r_obj;
};
If somebody tries to pass a temporary to setDataRef, overload resolution will prefer the T&& version but because it is deleted, the call is ill-formed. If somebody passes an lvalue, that will bind to the const reference.
Martin's suggestion is very nice and does prevent the caller from passing an rvalue to the function. But that still won't guarantee that the lifetime of the passed object extends beyond the lifetime of the Foo instance.
If the object stores a pointer to the passed object, it would be most intuitive, if a pointer were passed to the setter. Passing a pointer also prevents using an rvalue (because taking an address of an rvalue is not allowed).
Just like you have to document the interface that the passed object must exist as long as Foo instance exists, you can also document that the passed pointer must not be null. Additionally, you can assert it. You could similarly delete the overload for nullptr_t to prevent passing the literal to the setter but that won't prevent passing null pointers of T* type. In my opinion, the advantage of the reference setter is not great.
Of course, neither raw pointer, nor a reference tell the caller anything about ownership, so that must in either case be documented. Instead, I would recommend storing and passing a smart pointer. unique_ptr if Foo should have the ownership (apparently not), shared_ptr if Foo should keep the object alive if it goes out of scope elsewhere, or possibly weak_ptr if Foo should have a failure mode when referred object no longer exists. A smart pointer would be self documenting and intuitive for the user.

Distinguish between temporaries and non-temporaries in function signature?

I want to create a class Bar that can distinguish between temporaries and non-const non-temporaries. According to this (about 25% down the page), I can get away with this if the second StealPointer takes a const reference (to a pointer in my case), but in my code it just uses the StealPointer(Foo*&& foo) version regardless of how it is called.
class Foo {};
class Bar {
public:
// For when StealPointer(new Foo()); is called. Bar instance then owns the
// pointer.
void StealPointer(Foo*&& foo) {} // Get the temporaries only.
// For when a Foo* already exists and is passed in StealPointer(my_foo_ptr);
// Takes ownership and invalidates the pointer that the caller once had.
void StealPointer(Foo*&) {} // Get lvalues only.
};
Can I do this? Is there a way to do this that only requires one function? If it matters, Bar is going to store the pointer in a unique_ptr and I would like to avoid the additional syntax of passing in a unique_ptr or making the caller do something with std::move. I can't just pass the pointers by reference, because temporaries of type Foo* can't be converted to Foo*&.
Make your function templated and let std::unique_ptr worry about those details for you.
template <typename Ptr>
void StealPointer(Ptr&& p) // a universal reference, matches *any* type of value
{
uniqptr = std::move(p); // Works for both rvalues and lvalues
}

Why would you pass an object by pointer and not by reference? [duplicate]

I am new to C++ programming, but I have experience in Java. I need guidance on how to pass objects to functions in C++.
Do I need to pass pointers, references, or non-pointer and non-reference values? I remember in Java there are no such issues since we pass just the variable that holds reference to the objects.
It would be great if you could also explain where to use each of those options.
Rules of thumb for C++11:
Pass by value, except when
you do not need ownership of the object and a simple alias will do, in which case you pass by const reference,
you must mutate the object, in which case, use pass by a non-const lvalue reference,
you pass objects of derived classes as base classes, in which case you need to pass by reference. (Use the previous rules to determine whether to pass by const reference or not.)
Passing by pointer is virtually never advised. Optional parameters are best expressed as a std::optional (boost::optional for older std libs), and aliasing is done fine by reference.
C++11's move semantics make passing and returning by value much more attractive even for complex objects.
Rules of thumb for C++03:
Pass arguments by const reference, except when
they are to be changed inside the function and such changes should be reflected outside, in which case you pass by non-const reference
the function should be callable without any argument, in which case you pass by pointer, so that users can pass NULL/0/nullptr instead; apply the previous rule to determine whether you should pass by a pointer to a const argument
they are of built-in types, which can be passed by copy
they are to be changed inside the function and such changes should not be reflected outside, in which case you can pass by copy (an alternative would be to pass according to the previous rules and make a copy inside of the function)
(here, "pass by value" is called "pass by copy", because passing by value always creates a copy in C++03)
There's more to this, but these few beginner's rules will get you quite far.
There are some differences in calling conventions in C++ and Java. In C++ there are technically speaking only two conventions: pass-by-value and pass-by-reference, with some literature including a third pass-by-pointer convention (that is actually pass-by-value of a pointer type). On top of that, you can add const-ness to the type of the argument, enhancing the semantics.
Pass by reference
Passing by reference means that the function will conceptually receive your object instance and not a copy of it. The reference is conceptually an alias to the object that was used in the calling context, and cannot be null. All operations performed inside the function apply to the object outside the function. This convention is not available in Java or C.
Pass by value (and pass-by-pointer)
The compiler will generate a copy of the object in the calling context and use that copy inside the function. All operations performed inside the function are done to the copy, not the external element. This is the convention for primitive types in Java.
An special version of it is passing a pointer (address-of the object) into a function. The function receives the pointer, and any and all operations applied to the pointer itself are applied to the copy (pointer), on the other hand, operations applied to the dereferenced pointer will apply to the object instance at that memory location, so the function can have side effects. The effect of using pass-by-value of a pointer to the object will allow the internal function to modify external values, as with pass-by-reference and will also allow for optional values (pass a null pointer).
This is the convention used in C when a function needs to modify an external variable, and the convention used in Java with reference types: the reference is copied, but the referred object is the same: changes to the reference/pointer are not visible outside the function, but changes to the pointed memory are.
Adding const to the equation
In C++ you can assign constant-ness to objects when defining variables, pointers and references at different levels. You can declare a variable to be constant, you can declare a reference to a constant instance, and you can define all pointers to constant objects, constant pointers to mutable objects and constant pointers to constant elements. Conversely in Java you can only define one level of constant-ness (final keyword): that of the variable (instance for primitive types, reference for reference types), but you cannot define a reference to an immutable element (unless the class itself is immutable).
This is extensively used in C++ calling conventions. When the objects are small you can pass the object by value. The compiler will generate a copy, but that copy is not an expensive operation. For any other type, if the function will not change the object, you can pass a reference to a constant instance (usually called constant reference) of the type. This will not copy the object, but pass it into the function. But at the same time the compiler will guarantee that the object is not changed inside the function.
Rules of thumb
This are some basic rules to follow:
Prefer pass-by-value for primitive types
Prefer pass-by-reference with references to constant for other types
If the function needs to modify the argument use pass-by-reference
If the argument is optional, use pass-by-pointer (to constant if the optional value should not be modified)
There are other small deviations from these rules, the first of which is handling ownership of an object. When an object is dynamically allocated with new, it must be deallocated with delete (or the [] versions thereof). The object or function that is responsible for the destruction of the object is considered the owner of the resource. When a dynamically allocated object is created in a piece of code, but the ownership is transfered to a different element it is usually done with pass-by-pointer semantics, or if possible with smart pointers.
Side note
It is important to insist in the importance of the difference between C++ and Java references. In C++ references are conceptually the instance of the object, not an accessor to it. The simplest example is implementing a swap function:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
The swap function above changes both its arguments through the use of references. The closest code in Java:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
The Java version of the code will modify the copies of the references internally, but will not modify the actual objects externally. Java references are C pointers without pointer arithmetic that get passed by value into functions.
There are several cases to consider.
Parameter modified ("out" and "in/out" parameters)
void modifies(T &param);
// vs
void modifies(T *param);
This case is mostly about style: do you want the code to look like call(obj) or call(&obj)? However, there are two points where the difference matters: the optional case, below, and you want to use a reference when overloading operators.
...and optional
void modifies(T *param=0); // default value optional, too
// vs
void modifies();
void modifies(T &param);
Parameter not modified
void uses(T const &param);
// vs
void uses(T param);
This is the interesting case. The rule of thumb is "cheap to copy" types are passed by value — these are generally small types (but not always) — while others are passed by const ref. However, if you need to make a copy within your function regardless, you should pass by value. (Yes, this exposes a bit of implementation detail. C'est le C++.)
...and optional
void uses(T const *param=0); // default value optional, too
// vs
void uses();
void uses(T const &param); // or optional(T param)
There's the least difference here between all situations, so choose whichever makes your life easiest.
Const by value is an implementation detail
void f(T);
void f(T const);
These declarations are actually the exact same function! When passing by value, const is purely an implementation detail. Try it out:
void f(int);
void f(int const) { /* implements above function, not an overload */ }
typedef void NC(int); // typedefing function types
typedef void C(int const);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
Pass by value:
void func (vector v)
Pass variables by value when the function needs complete isolation from the environment i.e. to prevent the function from modifying the original variable as well as to prevent other threads from modifying its value while the function is being executed.
The downside is the CPU cycles and extra memory spent to copy the object.
Pass by const reference:
void func (const vector& v);
This form emulates pass-by-value behavior while removing the copying overhead. The function gets read access to the original object, but cannot modify its value.
The downside is thread safety: any change made to the original object by another thread will show up inside the function while it's still executing.
Pass by non-const reference:
void func (vector& v)
Use this when the function has to write back some value to the variable, which will ultimately get used by the caller.
Just like the const reference case, this is not thread-safe.
Pass by const pointer:
void func (const vector* vp);
Functionally same as pass by const-reference except for the different syntax, plus the fact that the calling function can pass NULL pointer to indicate it has no valid data to pass.
Not thread-safe.
Pass by non-const pointer:
void func (vector* vp);
Similar to non-const reference. The caller typically sets the variable to NULL when the function is not supposed to write back a value. This convention is seen in many glibc APIs. Example:
void func (string* str, /* ... */) {
if (str != NULL) {
*str = some_value; // assign to *str only if it's non-null
}
}
Just like all pass by reference/pointer, not thread-safe.
Since no one mentioned I am adding on it, When you pass a object to a function in c++ the default copy constructor of the object is called if you dont have one which creates a clone of the object and then pass it to the method, so when you change the object values that will reflect on the copy of the object instead of the original object, that is the problem in c++, So if you make all the class attributes to be pointers, then the copy constructors will copy the addresses of the pointer attributes , so when the method invocations on the object which manipulates the values stored in pointer attributes addresses, the changes also reflect in the original object which is passed as a parameter, so this can behave same a Java but dont forget that all your class attributes must be pointers, also you should change the values of pointers, will be much clear with code explanation.
Class CPlusPlusJavaFunctionality {
public:
CPlusPlusJavaFunctionality(){
attribute = new int;
*attribute = value;
}
void setValue(int value){
*attribute = value;
}
void getValue(){
return *attribute;
}
~ CPlusPlusJavaFuncitonality(){
delete(attribute);
}
private:
int *attribute;
}
void changeObjectAttribute(CPlusPlusJavaFunctionality obj, int value){
int* prt = obj.attribute;
*ptr = value;
}
int main(){
CPlusPlusJavaFunctionality obj;
obj.setValue(10);
cout<< obj.getValue(); //output: 10
changeObjectAttribute(obj, 15);
cout<< obj.getValue(); //output: 15
}
But this is not good idea as you will be ending up writing lot of code involving with pointers, which are prone for memory leaks and do not forget to call destructors. And to avoid this c++ have copy constructors where you will create new memory when the objects containing pointers are passed to function arguments which will stop manipulating other objects data, Java does pass by value and value is reference, so it do not require copy constructors.
Do I need to pass pointers, references, or non-pointer and non-reference values?
This is a question that matters when writing a function and choosing the types of the parameters it takes. That choice will affect how the function is called and it depends on a few things.
The simplest option is to pass objects by value. This basically creates a copy of the object in the function, which has many advantages. But sometimes copying is costly, in which case a constant reference, const&, is usually best. And sometimes you need your object to be changed by the function. Then a non-constant reference, &, is needed.
For guidance on the choice of parameter types, see the Functions section of the C++ Core Guidelines, starting with F.15. As a general rule, try to avoid raw pointers, *.
There are three methods of passing an object to a function as a parameter:
Pass by reference
pass by value
adding constant in parameter
Go through the following example:
class Sample
{
public:
int *ptr;
int mVar;
Sample(int i)
{
mVar = 4;
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value of the pointer is " << *ptr << endl
<< "The value of the variable is " << mVar;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
char ch;
cin >> ch;
}
Output:
Say i am in someFunc
The value of the pointer is -17891602
The value of the variable is 4
The following are the ways to pass a arguments/parameters to function in C++.
1. by value.
// passing parameters by value . . .
void foo(int x)
{
x = 6;
}
2. by reference.
// passing parameters by reference . . .
void foo(const int &x) // x is a const reference
{
x = 6;
}
// passing parameters by const reference . . .
void foo(const int &x) // x is a const reference
{
x = 6; // compile error: a const reference cannot have its value changed!
}
3. by object.
class abc
{
display()
{
cout<<"Class abc";
}
}
// pass object by value
void show(abc S)
{
cout<<S.display();
}
// pass object by reference
void show(abc& S)
{
cout<<S.display();
}

yet another issue with call by value|reference

The question is simple and may has been discussed before, but I could find a clear answer for my case. Assume I pass a pointer object to a function
#include "foo.h"
int main()
{
foo * aFoo = new foo;
bar(aFoo);
delete aFoo;
aFoo = NULL;
return 0;
}
Then the function is written like this
void bar (foo *f)
{
f->insert();
}
The question:
Is that a call by value or call by reference? I know in call by value, there is an overhead for copying the object from main() to bar(). So I want to be sure that is a call by reference.
It is a call by value, where the value of the pointer aFoo is being copied into the function parameter f.
A call by reference is a call where the parameter is a reference, and side-effects on the argument (and not on objects possibly pointed to by that argument) which occur inside the function are visible to the caller when the function returns.
So for instance this is a function accepting a parameter by reference:
void bar(foo*& f)
// ^
// Here you are taking a pointer by reference
While this is a function accepting a parameter by value:
void bar(foo* f)
// ^
// Here you are taking a pointer to foo by value
You are probably puzzled by the fact that taking a foo by reference and writing:
void bar(foo& f)
{
f.insert();
}
Has pretty much the same effect as passing a pointer to the same foo object by value and writing:
void bar(foo* f)
{ // Precondition: f != nullptr
f->insert();
}
However, the two things are conceptually different. While the value/state of the object you passed in the first case can be different when the function returns from the value/state it had before calling the function, in the second case the value of the pointer you provided will be the same as it was before you called bar() - while the object pointed to may have undergone some state change.
Also notice, that a pointer can be null, while a reference is always bound to an object.
In your case, it is call by value in terms of the pointer to Foo formally. But since you pass a pointer to a function instead of the class instance itself, then it is conceptually call by reference in terms of the class instance since the function call does not copy the whole instance but just its pointer.
Foo fooInstance;
// providing a way to point (less formally you can call it refer) to the instance
Foo* fooPointer = &fooInstance;
// this function call is call by value (passing the value of the pointer).
// but you can logically view it as 'call by reference' to fooInstance.
bar(fooPointer);

Confusion in C++

I'm very new to C++ and I'm currently learning it. I got a few questions..
What is the differences between void DoSomething(const Foo& foo) and void DoSomething(Foo foo)? If we don't specify & then the instance of Foo will be passed by value ( not reference ). It will be the same as having const + & in argument except no checking at compile-time. So, Why does having const + & become the best practice over the argument without & and const?
In C#, passing the object is "by reference" but seems like it's not in C++.
The book that I'm reading said that Member functions pass the implicit parameter by reference..
Could anyone give me the sample of implicit parameter and by reference? I know that if we want to pass the object by reference, we need to use & (e.g. Foo(Person& p) ) but how come C++ pass the object by reference for implicit parameter? I read that implicit parameter in C++ is like Contructor(string str) : strMemberVariable(str) {} ...
Is the array the only that pass by reference in C++?
Why can't I use Foo fInstance in Foo class?
Example:
class Foo {
public:
Foo() { }
Foo(const Foo& f) : fInstance(f) { }
Foo fInstance;
};
Thanks in advance.
1 What is the differences between void DoSomething(const Foo& foo) and void DoSomething(Foo foo)? If we don't specify & then the instance of Foo will be passed by value ( not reference ). It will be the same as having const + & in argument except no checking at compile-time. So, Why does having const + & become the best practice over the argument without & and const?
In C#, passing the object is "by reference" but seems like it's not in C++.
There are several differences, in order of importance:
If the object Foo cannot be copied, you need to pass it by reference
If the object Foo is a base class, you should get it by reference so that users can call your functions with derived classes
The value of the actual object might change even though you hold a const reference to it
Efficiency, copying user types might be expensive, but compilers may be smart enough to figure it out so...
2 The book that I'm reading said that Member functions pass the implicit parameter by reference..
Could anyone give me the sample of implicit parameter and by reference? I know that if we want to pass the object by reference, we need to use & (e.g. Foo(Person& p) ) but how come C++ pass the object by reference for implicit parameter? I read that implicit parameter in C++ is like Contructor(string str) : strMemberVariable(str) {} ...
By implicit parameter you should understand this, that is the object itself. It is effectively passed by reference since you can modify its state in the member function.
Following Konrad's remark: note that this itself is not passed by reference, this is a reference (pointer) to the object, but is passed by value. You can't change the memory address of your object as you wish ;)
3 Is the array the only that pass by reference in C++?
They aren't. You will see changes to the elements of the array, but the array (structure) will not change.
Following FredOverflow's remark, an illustration:
void fun(int* p, size_t size);
int main(int argc, char* argv[])
{
int array[15];
fun(array, 15);
}
We don't know what fun does, it will probably change some elements of array, but whatever its action, array will remain an Array of 15 integers: the content changes, the structure does not.
As a result, to change array we need another declaration:
void changer(int*& array, size_t& size);
This way we can change both the content and the structure (and pass back the new size too). And of course we can only call this function with an array that was dynamically allocated.
4 Why can't I use Foo fInstance in Foo class?
Because that's infinite recursion. Think about it from a compiler point of view, and try to guess the size of Foo. The size of Foo is the sum of the sizes of its attributes, plus possibly some padding and type information. Also, an object size is at least 1 so that it can be addressed. So, if Foo has a Foo, what's its size :) ?
The usual solution is to use a smart pointer:
class Foo
{
public:
private:
std::unique_ptr<Foo> mInstance;
};
Because the size of a pointer does not depend on the size of the object pointed to, so there is not recursion going on here :)
Since there are so many misconceptions and downright false answers here, this is my attempt at redressing this:
What is the differences between void DoSomething(const Foo& foo) and void DoSomething(Foo foo)?
As others have said, the second code requires a copy (usually calling the copy constructor of Foo).
So, Why does having const + & become the best practice over the argument without & and const?
There are a few special purporses that others have already answered (e.g. runtime polymorphism). This doesn’t explain why it has become best practice. The reason for this is simple and ugly: because it is magnitudes more efficient. Imagine passing a vector or string to another method – or basically just any big data structure. The cost of copying this will generally be huge, and methods may be called often in code – in fact, methods are usually called very often, otherwise the code is badly designed.
On the other hand, when you pass the object as a const reference then this is internally (usually) implemented via a pointer. Pointers can always be copied efficiently, on all architectures.
The book that I'm reading said that Member functions pass the implicit parameter by reference..
I think the book is wrong. Member functions of classes implicitly get passed a this pointer that refers to the current object. However, this is a pointer, and C++ forbids changing it. There is no reason why it would be passed by reference.
Is the array the only that pass by reference in C++?
Arrays are rarely passed at all in C++ – they are usually passed as pointers:
void foo(int[] x) { … }
is actually the same as
void foo(int* x) { … }
The compiler treats these two declarations identical. When you try calling either of these methods and pass it an array x, C++ will implicitly convert the array to a pointer to its first element – this is called “decay”. So, foo(x) will become foo(&x[0]).
However, arrays can instead be passed by reference if their size is given:
void foo(int (&x)[4]);
But once again, you are explicitly declaring that the array be passed by reference.
In C#, passing the object is "by reference" but seems like it's not in C++.
No, this is wrong, it’s a common misconception. In languages like C#, VB and Java, variables are always passed by value (exception explicitly passed as ref in C# or ByRef in VB).
The difference to C++ is that variables don’t contain a class’ object itself, they only contain the reference. So what is passed to the method is not the object itself, only its reference (but that is passed by value).
The difference is rather important. If C# used pass by reference, the following code would print a different result:
void foo(string s) {
s = "world";
}
string s = "hello";
foo(s);
Console.WriteLine(s); // prints "hello"
Why can't I use Foo fInstance in Foo class?
Because conceptually, an object of Foo would need an infinite amount of space. Technically, the type Foo is incomplete in the definition of Foo.
What you probably want is a pointer to Foo as a member.
The difference between void DoSomething(const Foo& foo) and void DoSomething(Foo foo) is the first passes the parameter by reference and the second by value. The practical differences are:
Efficiency. Passing by value may require the copy constructor to be called. If the copy constructor is expensive, passing by value will add more overhead.
Applicability. Passing by value requires a public copy constructor. If a class does not support a copy constructor, it cannot be passed by value.
Semantics. When passing by reference, you don't know who the object may be referenced. If the underlying object is changed for some other reason, the value of the reference will change.
To explain #3 a bit better, consider this situation:
std::string global_string;
void foo(const std::string &str)
{
if (str.empty())
{
global_string = "whatever";
// is str still empty??
}
}
If foo is called as foo(global_string), then when you change global_string this also changesstr.
One at a time:
doStuff(Foo f) means a new Foo object will be created on the stack when the method is called - AKA by-value. Calling doStuff(const Foo &f) means you are just passing a new reference , object is not duplicated, you only hold a reference to it. This is the safest way of passing arguments since it does not involve duplicating a copy of an object. This is called passing by-reference and is the closest you will get to Java/C# behavior.
Which implicit parameter are you talking about?
Again, arrays (assuming they are std::arrays) can be passed by value, pointer, or reference - there is no single behavior. As Konard mentioned, C-style arrays (nothing more than blocks of memory) cannot be passed by value.
It's not quite accepted "good practice" to pass by const reference instead of by value.
This blog post explains why.
People tend to think that const reference is faster, but the truth is that the compiler is allowed to optimize away the copy when passing by value, so passing by value is a good default (and indeed, the standard library typically does this. For example, std::for_each takes two iterators by value and one functor by value)
The main reason to use const reference is if the object cannot logically be copied. Say the object represents a window. You don't want a second window to appear on screen just because you passed the window object to another function, implicitly creating a copy.
Many objects represents something that cannot or should not be copied. Those will typically have a private copy constructor, and will have to be passed by reference or const reference to functions.
Another reason to pass by reference (const or otherwise) might be to use polymorphic objects. Say you have a base class B and a derived class D. You can pass an object of type D as a const B& safely, but passing it by value as an object of type B risks introducing slicing (only the B subobject is copied, instead of the entire D object).
So a good practice is to pass by value by default, but passing by const reference certainly also has its place. Both are in the language for a reason.
What is the differences between void DoSomething(const Foo& foo) and
void DoSomething(Foo foo)?
pragmatically there is no difference, the const will prevent you from changing the contents of 'foo' whereas passing by value will also not affect the contents of the argument, however in terms of effectiveness the const Foo& foo is more effective since it wouldn't create a copy when the object is passed to the method.
The book that I'm reading said that Member functions pass the implicit parameter by reference..
The book is talking about the implicit pointer this that is passed to every non-static member function defined in a class. That because C++ holds a copy of each member function in the class not in every object so the method should know about what object of that class it should work on.
class FOO{
int x;
void doSomthing(int x);
}
void FOO::doSomething(int x){
x = x;
}
would be compiled into something like that
void FOO::doSomething(FOO* this, int x){
this->x = x;
}
Since static functions are class functions rather than object functions, they don't need an object to be created in order to be called, so they shouldn't have access to non-static fields of the class and thus doesn't need a this pointer to the object.
What is the differences between void
DoSomething(const Foo& foo) and void
DoSomething(Foo foo)?
Broadly speaking, the latter will deep copy the argument being passed (in other words, it makes a copy of the original Foo object). The former will make a shallow copy of the argument being passed (copying its address to an immutable const reference rather than copying the actual Foo object).
Both of these versions have access to the members of the Foo object being passed. Neither of them will modify the Foo object in the caller. The basic difference, provided that the function does not need a deep copy, is that the former is more efficient because it avoids the need to deep copy.
Could anyone give me the sample of implicit parameter and by reference? I know that if we want to pass the object by reference, we need to use & (e.g. Foo(Person& p) ) but how come C++ pass the object by reference for implicit parameter? I read that implicit parameter in C++ is like Contructor(string str) : strMemberVariable(str) {} ...
In the context of parameterized, unary constructors (constructors taking one argument), they can be implicit (default) or explicit.
class Foo
{
Foo(int x) {...}
};
This is implicit. It allows us to write code like:
Foo foo = 123;
void f(const Foo& x);
f(123);
While this is explicit:
class Foo
{
explicit Foo(int x) {...}
};
... and would not the previous code. The previous code would have to be modified accordingly:
Foo foo(123);
void f(const Foo& x);
f(Foo(123) );
It is generally a good habit to make such constructors explicit, with the exception of the copy constructor which I won't go into here as that gets rather involved.
Is the array the only that pass by
reference in C++?
I am not exactly sure what is being asked here, but arrays cannot be passed by value if that's what you mean. We can only pass around references/pointers to arrays:
// takes an array of 10 integers
void fn(int(&some_array)[10]);
// takes a pointer to an int array
void fn(int* some_array);
// takes a pointer to an int array (the 10
// literal constant is ignored) and this function
// can likewise take any pointer to int
void fn(int some_array[10]);
Why can't I use Foo fInstance in Foo
class?
That's infinitely recursive. Foo stores fInstance, fInstance stores another fInstance, and so on. There's nothing to stop the recursion so you'd just have objects storing objects storing objects storing objects and so on until you run out of memory. Thus compilers detect that condition and disallow since no legitimate runtime behavior can come of it. There would also be no way to determine the size of Foo - that would be an infinite value.
void DoSomething(Foo foo)
Actually passes a copy of foo, and
void DoSomething(Foo& foo)
Passes a reference to foo, so if you modify foo in your function, you'll modify the original foo. I hope this makes sense.
As for arrays, an array is actually a pointer to the beginning of an array, and that pointer is passed around (the whole array is not copied).
array[5] = 0;//is the same as :
*(array+5) = 0; //this
What is the differences between void DoSomething(const Foo& foo) and void DoSomething(Foo foo)
DoSomething(Foo foo) passes the object foo by value if Foo is a primitive data-type, but by reference if Foo is a user defined data-type. But in the second case, if you change foo, it gets reflected back to the original object, which is often undesirable. This is taken care of by DoSomething(const Foo& foo) which passes foo by reference (thus saving the extra memory cost of passing by value) and still does not give write access on foo to the DoSomething function. Thus, it is a best practice.
Could anyone give me the sample of
implicit parameter and by reference?
An example of implicit parameter in member functions is the reference to the parent object, ie. this which is never mentioned in the function's definition, but always available for use.
Is the array the only that pass by
reference in C++?
No, all user defined objects are passed by reference.