I do not understand what is going on. I am just learning C++ and I see something like this a lot:
double some_function(const Struct_Name& s) {
...
}
Why the const if we are passing by reference?
You pass by const reference when you don't want to(or can't) modify the argument being passed in, and you don't want the performance hit that you might get from copying the object.
A const reference prevents the object from being modified, as const would anywhere else, but also avoids the potential cost of copying.
You are telling the compiler you're not going to change s, ever.
This enables it to make some optimizations it wouldn't have been able to do otherwise. Basically, it gives you the same semantics as passing by value, but doesn't incur the performance penalty of calling the copy constructor.
Call by const-reference avoids a copy of the Struct_Name while promising not to modify it.
There is both a performance reason for this, and a semantics reason.
If Struct_Name is large, copying it is expensive in both time and memory.
If Struct_Name is uncopyable (or becomes invalid when copied) calling by value is impossible or introduces undesirable complexity. For example: std::unique_ptr and std::auto_ptr.
By using const we can signal both the user of the function and the compiler that the object passed as the argument s will not be changed inside the function (which would actually be possible, because we pass it by reference!). The compiler can than give us an error if we modify the object by accident and it can do some optimizations it couldn't do otherwise.
An additional advantage is, that if the caller of the function only owns a const pointer to an object, it can still provide that object as an argument without casting.
const here promisses that some_function will not modify s parameter,
double some_function(const Struct_Name& s) {
...
}
you can try modifying it but compiler will return errors. Actually constness requires you to carefully write Struct_Name internal methods, ie. you will not be able to call inside some_function non-const functions on s object. You can try, but you will get error. ie:
struct Struct_Name {
void myfun() const { } // can be called from some_function
void myfun2() { } // will show error if called from some_function
};
Using const parameter is good from design point of view, if you know some function is not supposed to change your object then you add const. This means that no other programmer can do changes in some deeply hidden in classes hierarchy code, that will modify your object. It really makes debugging easy.
Another reason that noone has mentioned yet - passing by a const reference allows the compiler to create and pass a temporary object, without generating a warning, if the input value is not the exact type declared in the parameter, but the type has a constructor that supports the type being passed in.
For example:
void foo(const std::string &s)
{
...
}
foo("hello"); // OK
foo() is expecting a std::string but receives a const char* instead. Since std::string has a constructor that accept a const char*, the compiler generates code that is effectively doing this:
std::string temp("hello");
foo(temp);
The compiler knows the parameter is const, the temporary will not be altered by foo(), and the temporary will be discarded after foo() exits, so it does not complain about having to create a temporary.
The same thing happens if the parameter is passed by value (const or non-const, it does not matter) instead of by reference:
void foo(const std::string s)
{
...
}
void bar(std::string s)
{
...
}
foo("hello"); // OK
bar("world"); // OK
This is effectively the same as this:
{
std::string temp1("hello");
foo(temp1);
}
{
std::string temp2("world");
bar(temp2);
}
Again, the compiler does not complain, as it knows the temporary does not affect the calling code, and any alterations made to the temporary in bar() will be safely discarded.
If the parameter were a non-const reference instead, passing a const char* would generate a warning about the temporary that has to be created to satisfy the reference binding. The warning is to let you know that any changes the function makes to the temporary (since it is not const) will be lost when the function exits, which may or may not have an effect on the calling code. This is usually an indication that a temporary should not be used in that situation:
void foo(std::string &s)
{
...
}
foo("hello"); // warning!
Related
I have a function which accepts a Large by const reference:
void func(const Large& param);
and a class which holds a Large:
class HoldsLarge {
public:
Large GetByValue() const { return l; };
private:
Large l;
}
If I do
HoldsLarge x;
func(x.GetByValue());
am I correct in understanding that a temporary will be copy constructed for x.GetByValue() which will by passed by reference to func? Is there something in the standard which will allow a compiler to omit the construction of the temporary altogether? After all, func only need a const reference to HoldsLarge::l.
I understand I could simply return HoldsLarge::l by const reference but I would like to prevent clients from accidentally creating a dangling reference.
Compiler is allowed to change behavior (as optimization) in few cases: for NRVO, and since C++14 for new expression.
You are not in those cases.
Then; as-if rule allows any optimizations as long as observable behavior is identical.
So compiler can do the optimization only if that doesn't change the behavior.
Without knowing func, it cannot safely do that.
func might have access to x.l (or alias) from another way (as global).
For example, following func would prohibit the change.
Large* largePtr; // possibly set to &x.l by any way
void func(const Large& param)
{
print(param.x);
//param might be alias of largePtr
mutate(alias->x);
print(param.x); // const ref should see the modification
// whereas copy don't
}
If we have this class definition
class BusDetails
{
private:
string m_busName;
public:
string BusName() const { return m_busName; }
};
how could the getter method be changed or used, so that using the return value as an lvalue would give a compiler error?
For example, if I use it like
int main(void)
{
BusDetails bus;
bus.BusName() = "abc"; // <--- This should give a compiler error
cout << bus.BusName() << endl;
return 0;
}
I get no compiler error, so apparently the assignment works, but the result is not as expected.
Update: this behavior is as expected with build-in types (i.e. the compiler gives an error at the above line of code if I have an int as a return type instead of string).
The BusName() was declared as a const function. So it can't change members.
Your function should return string& and not be const.
string& BusName() { return m_busName; }
In addition you can add for const object (this is const):
const string& BusName() const { return m_busName; }
It's not clear what behavior you want.
If you want the assignment to be an error, and keep all of the
flexibility of value return (e.g. you can modify the code to
return a calculated value), you can return std::string const.
(This will inhibit move semantics, but that's generally not
a big issue.)
If you want to be able to modify the "member", but still want
to retain flexibility with regards to how it is implemented in
the class, then you should provide a setter method. One
convention (not the only one) is to provide a getter function
like you have now (but returning std::string const), and
provide a function with the same name void
BusName( std::string const& newValue ) to set the value.
(Other conventions would use a name like SetBusName, or return
the old value, so client code could save and restore it, or
return *this, so client code could chain the operations:
obj.BusName( "toto" ).SomethingElse( /*...*/ ).
You may also provide a non-const member returning a reference
to a non-const. If you do this, however, you might as well make
the data member public.
Finally, you might provide a non-const member which returns
some sort of proxy class, so that assigning to it would in fact
call a setter function, and converting it to std::string would
call the getter. This is by far the most flexible, if you
want to support modifications by the client, but it's also by
far the most complex, so you might not want to use it unless you
need to.
Well it is kind of expected behavior what you have written.
You do return a copy of m_busName. Because you do not return the reference. Therefore a temporary copy of the return variable is made, and then the assignment takes place. operator= is "abc" called on that copy.
So the way to go would be string& BusName() const { return m_busName; }. But that shall give a compiler error.
You kind of want contradictory things. You say string BusName() const, yet you want to return a reference that will allow the state of the object to be changed.
However if you don't promise the object will not change you can drop the const and go with
string& BusName() { return m_busName; };
Or if you want to keep the const
const string& BusName() const { return m_busName; };
however this should give an error on the assignment, naturally.
The same goes for functions. If you do pass argument by reference it is a reference. If you see that you modify a copy, you must have not passed it by reference but by value.
The function does return an rvalue.
The problem is that std::string::operator= works with an rvalue on the left. Prior to C++11 it was difficult or impossible to prevent it from working: in C++11 they added (relatively late) what is colloquially known as rvalue references to this: the ability to overload methods and in-class operators based on the rvalue state of the object.
However, std::string was not modified, probably do to a mixture of not much time and dislike of breaking existing code without good reason.
You could patch around this problem a few ways. You could write your own string class that obeys rvalue reference to this. You could descend from std::string and block the operator= specifically. You could write an accessor object that has-a std::string that can cast-to std::string&& a d std::string& (based on rvalue status of this) implicitly, but blocks assignment with deleted method.
All three have issues. The last has the fewest issues, the second the most hidden pitfalls, the first is just drudgery.
Sometimes we like to take a large parameter by reference, and also to make the reference const if possible to advertize that it is an input parameter. But by making the reference const, the compiler then allows itself to convert data if it's of the wrong type. This means it's not as efficient, but more worrying is the fact that I think I am referring to the original data; perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
The call to bar in this code fails. This is desirable, because the reference is not of the correct type. The call to bar_const is also of the wrong type, but it silently compiles. This is undesirable for me.
#include<vector>
using namespace std;
int vi;
void foo(int &) { }
void bar(long &) { }
void bar_const(const long &) { }
int main() {
foo(vi);
// bar(vi); // compiler error, as expected/desired
bar_const(vi);
}
What's the safest way to pass a lightweight, read-only reference? I'm tempted to create a new reference-like template.
(Obviously, int and long are very small types. But I have been caught out with larger structures which can be converted to each other. I don't want this to silently happen when I'm taking a const reference. Sometimes, marking the constructors as explicit helps, but that is not ideal)
Update: I imagine a system like the following: Imagine having two functions X byVal(); and X& byRef(); and the following block of code:
X x;
const_lvalue_ref<X> a = x; // I want this to compile
const_lvalue_ref<X> b = byVal(); // I want this to fail at compile time
const_lvalue_ref<X> c = byRef(); // I want this to compile
That example is based on local variables, but I want it to also work with parameters. I want to get some sort of error message if I'm accidentally passing a ref-to-temporary or a ref-to-a-copy when I think I'll passing something lightweight such as a ref-to-lvalue. This is just a 'coding standard' thing - if I actually want to allow passing a ref to a temporary, then I'll use a straightforward const X&. (I'm finding this piece on Boost's FOREACH to be quite useful.)
Well, if your "large parameter" is a class, the first thing to do is ensure that you mark any single parameter constructors explicit (apart from the copy constructor):
class BigType
{
public:
explicit BigType(int);
};
This applies to constructors which have default parameters which could potentially be called with a single argument, also.
Then it won't be automatically converted to since there are no implicit constructors for the compiler to use to do the conversion. You probably don't have any global conversion operators which make that type, but if you do, then
If that doesn't work for you, you could use some template magic, like:
template <typename T>
void func(const T &); // causes an undefined reference at link time.
template <>
void func(const BigType &v)
{
// use v.
}
If you can use C++11 (or parts thereof), this is easy:
void f(BigObject const& bo){
// ...
}
void f(BigObject&&) = delete; // or just undefined
Live example on Ideone.
This will work, because binding to an rvalue ref is preferred over binding to a reference-to-const for a temporary object.
You can also exploit the fact that only a single user-defined conversion is allowed in an implicit conversion sequence:
struct BigObjWrapper{
BigObjWrapper(BigObject const& o)
: object(o) {}
BigObject const& object;
};
void f(BigObjWrapper wrap){
BigObject const& bo = wrap.object;
// ...
}
Live example on Ideone.
This is pretty simple to solve: stop taking values by reference. If you want to ensure that a parameter is addressable, then make it an address:
void bar_const(const long *) { }
That way, the user must pass a pointer. And you can't get a pointer to a temporary (unless the user is being terribly malicious).
That being said, I think your thinking on this matter is... wrongheaded. It comes down to this point.
perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
Taking the address of a const& that happens to be a temporary is actually fine. The problem is that you cannot store it long-term. Nor can you transfer ownership of it. After all, you got a const reference.
And that's part of the problem. If you take a const&, your interface is saying, "I'm allowed to use this object, but I do not own it, nor can I give ownership to someone else." Since you do not own the object, you cannot store it long-term. This is what const& means.
Taking a const* instead can be problematic. Why? Because you don't know where that pointer came from. Who owns this pointer? const& has a number of syntactic safeguards to prevent you from doing bad things (so long as you don't take its address). const* has nothing; you can copy that pointer to your heart's content. Your interface says nothing about whether you are allowed to own the object or transfer ownership to others.
This ambiguity is why C++11 has smart pointers like unique_ptr and shared_ptr. These pointers can describe real memory ownership relations.
If your function takes a unique_ptr by value, then you now own that object. If it takes a shared_ptr, then you now share ownership of that object. There are syntactic guarantees in place that ensure ownership (again, unless you take unpleasant steps).
In the event of your not using C++11, you should use Boost smart pointers to achieve similar effects.
You can't, and even if you could, it probably wouldn't help much.
Consider:
void another(long const& l)
{
bar_const(l);
}
Even if you could somehow prevent the binding to a temporary as input to
bar_const, functions like another could be called with the reference
bound to a temporary, and you'd end up in the same situation.
If you can't accept a temporary, you'll need to use a reference to a
non-const, or a pointer:
void bar_const(long const* l);
requires an lvalue to initialize it. Of course, a function like
void another(long const& l)
{
bar_const(&l);
}
will still cause problems. But if you globally adopt the convention to
use a pointer if object lifetime must extend beyond the end of the call,
then hopefully the author of another will think about why he's taking
the address, and avoid it.
I think your example with int and long is a bit of a red herring as in canonical C++ you will never pass builtin types by const reference anyway: You pass them by value or by non-const reference.
So let's assume instead that you have a large user defined class. In this case, if it's creating temporaries for you then that means you created implicit conversions for that class. All you have to do is mark all converting constructors (those that can be called with a single parameter) as explicit and the compiler will prevent those temporaries from being created automatically. For example:
class Foo
{
explicit Foo(int bar) { }
};
(Answering my own question thanks to this great answer on another question I asked. Thanks #hvd.)
In short, marking a function parameter as volatile means that it cannot be bound to an rvalue. (Can anybody nail down a standard quote for that? Temporaries can be bound to const&, but not to const volatile & apparently. This is what I get on g++-4.6.1. (Extra: see this extended comment stream for some gory details that are way over my head :-) ))
void foo( const volatile Input & input, Output & output) {
}
foo(input, output); // compiles. good
foo(get_input_as_value(), output); // compile failure, as desired.
But, you don't actually want the parameters to be volatile. So I've written a small wrapper to const_cast the volatile away. So the signature of foo becomes this instead:
void foo( const_lvalue<Input> input, Output & output) {
}
where the wrapper is:
template<typename T>
struct const_lvalue {
const T * t;
const_lvalue(const volatile T & t_) : t(const_cast<const T*>(&t_)) {}
const T* operator-> () const { return t; }
};
This can be created from an lvalue only
Any downsides? It might mean that I accidentally misuse an object that is truly volatile, but then again I've never used volatile before in my life. So this is the right solution for me, I think.
I hope to get in the habit of doing this with all suitable parameters by default.
Demo on ideone
is it possible to restrict class instances to be used only as rvalues (e.g. temporaries)?
for example, I have class Wrapper whose constructor takes A const& and saves this reference in its member. It's a dangerous because lifetime of Wrapper instance cannot be longer than lifetime of A instance, but it's fine if Wrapper is temporary.
I think that even wanting to do this is a sign of a really bad design.
However, you could make all constructors private and make a friend function that returns an rvalue. That should do the trick.
I don't think it would be safe:
const A &a = YourClass( tmp );
YourClass in this case is the class you're looking for which only allow temporary instances, tmp is the temporary value you pass to the constructor.
It's possible (ie: safe, defined behavior) to have a constant reference to a temporary (ie: a), but the temporary itself (such instance of YourClass) has got a reference to tmp which is no longer valid after that expression is evaluated.
Not exactly the answer you are looking for, but have you thought about weak pointers? (for example, boost::weak_ptr). In this case, the original A would be held in a shared_ptr and the Wrapper constructor accepts a weak_ptr. The neat thing with this approach is that, before each usage of the weak_ptr, you can attempt to lock() which will give you a shared_ptr - if that fails, you know that A is gone and Wrapper cannot function... But it's handled cleanly...
This might do the job unless your class has public data members.
Basically, the idea is not to restrict the construction of the wrapper but to make sure that instances can be used (just like you said) only as long as they are temporary values. One can achieve this by overloading all methods and deleting (or making them private) those that refer to const&.
Here's a simple example:
class Wrapper
{
public:
Wrapper() = default;
Wrapper(const std::string& name) : name(name) {}
void process() && { std::cout << "Greetings from " << name << std::endl; }
// Only temporary instances of this class are allowed!
void process() const & = delete;
private:
std::string name;
};
And some use cases:
Wrapper("John").process(); // intended use case
Wrapper j; // create whatever you want
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
std::move(j).process(); // this is still possible
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ...
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
The obvious disadvantages are:
You have to overload every public member function.
The error message is delayed and not very informative.
A similar thing has been done in the standard. The make routines for std::reference_wrapper do not accept temporaries.
Note that they considered another subtlety: the overload uses const T&& instead of T&&. This can be important in our case as well. For example, if your wrapper is deliberately designed to be noncopyable and you use make routines such as
const Wrapper make_wrapper();
instead of
Wrapper make_wrapper();
In this case, you might want to replace
void process() &&;
by
void process() const &&;
I'd not bother enforcing this at compile time, as there are always going to be corner cases where this would be overly restrictive, limiting the usefulness of the class, but rather wrap tools like valgrind or Purify so I can spot places where invalidated references are used.
I believe in C++17 and later you can get approximately what you want by doing the following:
Delete the move constructor for your type (and don't define a copy constructor).
Always accept your type by value in APIs.
So, for example:
#include <type_traits>
#include <utility>
// A non-moveable, non-copyable type.
struct CantMove {
CantMove(CantMove&&) = delete;
CantMove(int) {} // Some other constructor
};
static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);
// A function that accepts it by value.
bool AcceptByValue(CantMove input) { return true; }
// It's possible to call the value-accepting API when the input is a prvalue
// (which in previous versions of C++ would have been a temporary).
bool unused = AcceptByValue(CantMove(0));
// But it's not possible to call with a named value, even when casted to an
// rvalue reference. This doesn't compile.
CantMove cant_move(0);
bool unused_2 = AcceptByValue(std::move(cant_move));
It's possible to provide the value-accepting function with what we previously called a temporary because guaranteed copy elision says that there isn't even a temporary involved anymore—the only CantMove object created is the function parameter itself, so there is no move- or copy-construction involved. In contrast it's not possible to call with std::move(cant_move) because that would involve move-constructing the function parameter, and the type is not move-constructible.
Of course it's still possible to initialize a CantMove directly:
CantMove foo{0};
But if you own all of the APIs that accept a CantMove and make them all accept by value, then you can't actually do anything with foo afterward. This means it would be hard for a user to do this by mistake and not realize the problem.
Yes, you could.
You would make the constructor and regular copy-constructor/assign private but make the r-value move semantics (C++0x) public.
You would have a static or friend constructor to create the temporary.
In 2003 C++ you would also be able to use this to bind to a const reference.
Of course you'd have the issue that your const reference would probably become invalidated after the statement.
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.