Does passing parameters by reference in C++ have to be manual? - c++

I am learning C++ and was reading a book on it where I came across this:
struct Vector{
int size;
double* elem;
}
void vector_init(Vector& v, int s){
v.size = s;
v.elem = new double[s];
}
So here, would void vector_init(Vector v, int s), without the reference operator, be wrong? Do I have to manually pass by reference using & while passing objects, structs, arrays or anything else as parameters? Also are there any alternate ways to do this? like say void vector_init(Vector *v, int s)?
Any help is appreciated.

There is no "reference operator".
The & declarator only gets added to the function parameter you want to be passed by reference. Passing a reference argument looks identical to passing by value.

would void vector_init(Vector v, int s), without the reference operator, be wrong?
If you don't pass v by reference, a copy of v will be made when enters function vector_init and you operate on that copy. After vector_init returns that temporary copy will be destroyed, so vector_init has no effect to your original v. To manipulate on original v, you need to pass v by reference(same to other type).
Also are there any alternate ways to do this? like say void vector_init(Vector *v, int s)?
Pass by reference is better choice compare to pass by pointer.

Actually passing a value by reference (void vector_init(Vector &v, int s)) or by pointer void vector_init(Vector *v, int s) have basically the same meaning.
The main difference is that when you pass by reference you are forced to pass a valid parameter (NULL wouldn't work) and that when you pass by pointer you must explicitly convert your argument to a pointer (while this is automatically done when passing by reference)
When you pass something by value as in void vector_init(Vector v, int s) it's different: the argument is copied through copy constructor and every modification made inside the scope of the function is local to the local copy of the argument, you cannot modify the original argument through a pass by value. You are not really passing your variable, you are passing a copy of it.
This even means that, if the argument is a large class or struct or has an expensive copy constructor, then also performance issues can occur.

Related

Reference from literal

I am calling a function with the signature
void setValue(int& data)
I would like to pass a literal number to it:
setValue(1);
But I get:
error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
Is there a way I can make this work without changing the function (it's in a library) and without assigning each literal value to a variable?
Assuming setValue does not actually modify its argument and just has a wrong signature which you cannot change, here is an approach which is not thread-safe among other things:
#include <iostream>
void setValue(int &i)
{
std::cout << "i = " << i << std::endl;
}
int& evil(int i)
{
static int j;
j = i;
return j;
}
int main()
{
setValue(evil(1));
setValue(evil(2));
}
When you declare the argument as being an int&, you are saying that the function called can change the value and the caller will see the change.
So it is no longer valid to pass a literal value then because how could the function possibly change the given value of a literal?
If you don't want the setValue to be able to change the given value, make the argument either be an int or const int&. And if you do want the setValue function to be able to change the value, then the caller must declare a non-const variable to hold the int and pass in that.
Can I change something at the call site to make it work
The problem with your code is that you declared your function to expect a reference, which means the compiler has to prepare the code to allow the function to change whatever you pass into it at the call site. So yes, sure, you can declare a variable, set it to 1 and call your function with it.
Contrast this with a constant reference in the declaration, where the compiler knows you won't change it inside the function, and then you can pass a literal in without issues. In fact, any logical, thought out design will make setters accept constant parameters because it won't change them, it will just store a possibly processed value in its state.
The answer to „what do I do if a library has a bad interface and I can't change it“ is usually „write a wrapper“. Assuming this is a method of some class BadLibraryClass, you could do something like:
class Wrapper {
public:
BadLibraryClass inner;
setValue(int i) {
inner.setValue(i); // i is an lvalue
}
};
This is just a crude example. Perhaps inner is better off being a pointer, a reference or even a smart pointer. Perhaps you want a conversion operator to BadLibraryClass. Perhaps you can use inheritance to expose other methods of BadLibraryClass.
Two options:
Use the result of assignment:
static int _data;
void myCall() {
setValue((_data = 3));
}
Write a wrapper:
struct setValueW {
int _data;
// constructor
setValueW(int _data) : _data(_data) {
setValue(_data);
}
// if you want to call it again
void operator()() {
setValue(_data);
}
};
void myCall2() {
setValueW(3);
}
AFAIK, references keeps the addresses of the variable. 1 is not variable. It is temporary.
Take a look this article(this is a quote from this site)
c++11 introduced a new kind of reference variable -- an r-value reference
To declare one, use && after a type
int & // type designation for an L-value reference
int && // type designation for an R-value reference
L-value references can only refer to L-values
R-value references can reference to R-values (temporaries)
int x, y, z; // regular variables
int & r = x; // L-value reference to the variable x
int & r2 = x + y; // This would be ILLEGAL, since x + y is an R-value
int && r3 = x + y; // LEGAL. R-value reference, referring to R-value
So you can use (But this is not useful. It may be more useful if you write this in plain without rvalue or lvalue.):
void setValue(int&& data)
setValue(1);
Or you can use that:
void setValue(int& data)
int a = 11;
setValue(a);
Don't forget for second example. If you change the value of data parameter. You will have change the a variable value.
No, you can't.
An lvalue reference like that binds to a variable (roughly speaking).
Your literal is not such a thing. It never had a name, and may not even have a home in memory.
Your two options are the two things you ruled out, I'm afraid.
For what it's worth, this is not your fault: that is a rather poor setter. It should take const int& (which will automatically create a nice temporary variable for you out of the literal!), or even just const int.

Do function parameter variables always require a & or * operator?

I'm reteaching myself C++ and as I'm reading about pointers a question has came into mind.
When declaring function signatures in C++, the address-of and dereference operators are used, such as the below.
int someFunction(std::vector<int>& nums) {
//do stuff
}
In this context the & is being used to declare that the address of the nums variable is being used rather than the value.
If this signature is changed to the below, the value is being used instead.
int someFunction(std::vector<int>* nums) {
//do stuff
}
However if the below is now used, I assume the value of the nums variable is still being used despite the lack of operator.
int someFunction(std::vector<int> nums) {
//do stuff
}
If this is true, since the lack of an operator and the * operator both result in the same thing, why is there any need for the * operator at all? Is it simply for brevity?
Those * and & in your code are neither dereference nor address-of operators. Both, * and & can have different meanings. Here they are part of the type:
int x; // declares an int
int* p; // declares a pointer to int
int& r = x; // declares a reference to int
The address-of and dereference operators come into play for example when you assign something to the above variables:
p = &x; // here & is address-of operator
x = *p; // here * is dereference operator
int someFunction(std::vector<int>& nums) {
//do stuff
}
In this context the & is being used to declare that the address of the nums variable is being used rather than the value.
No. Here the & means that nums is passed as reference.
If this signature is changed to the below, the value is being used
instead.
int someFunction(std::vector<int>* nums) {
//do stuff
}
No. Here nums is passed as pointer.
Only this is pass-by-value:
int someFunction(std::vector<int> nums) {
//do stuff
}
You are confusing things. In C++ arguments passed to a function are copied into the function. This is called "passing arguments by value", which is Ok for small types such as primitive types (int, double, etc), but it might be very costly for large objects. Imagine if your std::vector has 10 million elements.
In the first case with int someFunction(std::vector<int>& nums) the & indicates to the compiler that you want to pass the argment nums by reference, instead of the default by value. That means that the vector will not be copied into the function and a reference will be used instead (the cost here is like copying a single pointer). Note that since you are using a reference, if you modify nums inside your function the change will be visible outside the function (the variable passed as argument to the function will be changed). This is sometimes what you want and sometimes it is not. If you want to avoid the copy but don't want to change the vector, use int someFunction(const std::vector<int>& nums) instead.
In the second case you are actually passing just a pointer to the function and not a std::vector<int>, although the pointer points to an std::vector<int>. Similarly to the previous case, only a pointer is copied no matter how many elements the vector has and any change you made the the pointed vector will be visible outside the function. Note, however, that pointers can be null, while references cannot. That means that you would need to check if the pointer is null.
The third case is the default "passing by value" and a vector is copied into the function. Any change you make in the vector will not be visible outside the function, since you only changed the copy. But the cost can be high if the vector as many elements.

Correct way to use reference lvalues

My code is the following:
void parentheses (int n, string& str, int left, int right){
... irrelevant...
}
void solve(int n){
parentheses(n,"",0,0);
}
However, this will give me an error, telling me that cannot bind non-const lvalue reference of type std::__cxx11::string& ... to an rvalue of type ‘std::__cxx11::string. In this case, if I still want to pass the string in as a reference, how should I modify my functions? I don't want to make them const because I want to functions to modify the original string, and I want them to be & precisely because I want to edit their values.
The function parentheses expects an lvalue in the std::string parameter, i.e. a named variable. However, you have supplied an rvalue (temporary) in this call:
parentheses(n,"",0,0);
An empty string object is created and passed to parentheses. You can avoid this problem by changing the definition of parentheses like so:
void parentheses (int n, const string& str, int left, int right)
Here str will bind to an rvalue/temporary, but you won't be able to change its value in the function. However, if you want to change the value of str you have to define a string variable and pass that to the function.
Example:
void solve(int n){
std::string str;
parentheses(n,str,0,0);
}
Note: no need to assign str to "" as a string is empty by default.
the function needs a memory to change, you didn't specify which.
declare a string to hold what you want to pass and where to get the output to.
string s = "";
and pass it to the function
I'm not really sure what the purpose is of passing "" by reference is, as any value put there will get lost.
Anyway, to answer your question, create a variable and pass it instead:
void solve(int n){
std::string tmp = "";
parentheses(n,tmp,0,0);
}
If you don't care about the value stored in tmp, you can just ignore it. But you need some type of variable there, even if you don't care about what gets eventually put there by the routine.
Your parentheses() function takes a non-const reference to a std::string object, so it expects an actual std::string object on the other side of the reference - an lvalue (something that can be assigned to).
But your solve() function is not passing a std::string object, it is passing a string literal instead. So the compiler creates a temporary std::string object - an rvalue - which then fails to bind to the reference, because a temporary object can't be bound to a non-const reference, only to a const reference. That is what the error message is telling you:
cannot bind non-const lvalue reference of type std::__cxx11::string& ... to an rvalue of type ‘std::__cxx11::string
solve() needs to explicitly create an actual std::string object to pass to parentheses():
void solve(int n){
std::string s = "";
parentheses(n,s,0,0);
}
If you want to change the values of your string for any string that is passed as a paramenter (lvalue, as well rvalue), just initialize a variable with the intended content and pass it to your function.
But if you want to treat lvalue strings diferently from rvalue strings, just overload your original function. i.e.:
void parentheses (int n, string& str, int left, int right){
... irrelevant... // change strings values as desired
}
void parentheses (int n, string&& str, int left, int right){
... irrelevant... // string as rvalue
}

Passing temporary objects as argument (C++)

Temporary objects are sometimes created in C++. One example from the STL valarray class would be the slice_array, which is invoked every time a series of indices of a valarray is selected.
http://www.cplusplus.com/reference/valarray/slice_array/
My question is this:
When passing these temporary objects as arguments to a function, is a copy of these objects passed, or only a reference?
E.g. imagine these two naive functions:
double simple_product(double* inp,int length){
double res=1;
for(int i=0;i<length;++i){
res = res*inp[i];
}
return(res);
}
double sum_selected(valarray<double> v){
simple_product(&v[0],v.size());
return(v.sum());
}
If I call them in the following fashion:
valarray<double> valery(10,10);
size_t sel[] = {1,3,4};
valarray<size_t> selection (sel,3);
cout << sum_selected(valery[selection]);
will a new object with a size of 3*size_t be temporarily created within the stack of the function sum_selected or not?
Please note that declaring the function as: double sum_selected(valarray<double> & v)
is not permitted (temporary objects can only be bound to const references).
The reason why this is interesting is that, for example here, it is not possible to declare the function as:
double sum_selected(const valarray<double> & v), because then the function simple_product (which is to be assumed unalterable) cannot be called. However, making a temporary copy of the passed argument would be problematic for memory in case of big arrays.
If the function is declared to take its argument by value, then it's passed by value, creating a new copy of the object:
void f(thing t); // pass by value
If it's declared to take its argument by reference, then it's passed by reference. But it can only take a temporary by const or rvalue reference:
void f(thing const & t); // OK: const lvalue reference
void f(thing && t); // OK: rvalue reference
void f(thing & t); // Error: lvalue reference can't bind to temporary
Passing by reference doesn't create a new object, and the lifetime of the temporary is such that it's valid during the function call, until the end of the statement that creates it.
valarray<T>::operator[](valarray<size_t> const&) returns an indirect_array<T> (reference), or a valarray<T> for the const-qualified operator, not a slice_array.
If you want to be able to access the selected elements as a contiguous array, then you'll need to collect them into a contiguous array. The converting constructor valarray<T>::valarray(indirect_array<T> const&) does this for you. Reference semantics would be useless in this case, as there is no existing object that has your desired elements arranged contiguously.
Changing the function signature to double sum_selected(valarray<double> const&) would make no difference to your code, as a temporary valarray<double> is constructed anyway. It would be more efficient in the case where valery is passed directly, without subscripting.

What is a reference in C?

I have just started C++ and have come across references and have not understood completely.
References , as i read is an alternative name for an object.Why use that instead of directly accessing the object as any operation on references is directly reflected on the object ...?
Why and when are they used ?
Is ist like a constant pointer that is referenced each time it is used ... ?
And , it says
double& dr = 1; ---- says it is an error (some lavalue needed)
const double& cdr = 1; ---- says it is ok.
i dont understand it properly..So please explain why it is so ...
Thank You...:)
Why use that instead of directly
accessing the object as any operation
on references is directly reflected on
the object ...?
C++ passes parameters by value, meaning if you have a function such as:
void foo(MyObject o) { ... }
By default C++ will make a copy of a MyObject, not directly use the object being passed in. So, one use of references is to ensure you are working on the same object:
void foo(MyObject &o) { ...}
Or, if you aren't modifying o:
void foo(const MyObject &o) { ... }
References are another way of what was originally in C code like this
void fubarSquare(int *x){
int y = *x;
*x = y * y;
}
// typical invocation
int z = 2;
fubarSquare(&z);
// now z is 4
with references in C++ it would be like this
void fubarSquareCpp(int& x){
x = x * x;
}
// typical invocation
int z = 2;
fubarSquareCpp(z);
// now z is 4
It's a neater syntactical way of using a call-by-reference parameter instead of using the C's notation asterisk/star to indicate a pointer and as a call-by-reference parameter...and modifying the parameter directly outside of the function...
Have a look at Bjarne Stoustrap's page here which covers how C++ is and also here on the technical faq here
A reference is basically a pointer that looks like an object. It is very very hard to get a NULL reference though you can go through hoops and create one.
With regards to your example, 1 is an rvalue or a result. It is just a temporary variable and can not be modified. Thus you can't take a non const reference to it. However you can take a const reference to it. This means you can't change the value of the reference.
Here is an example of creating a NULL reference. Don't do it!
int * x = (int *)NULL;
int & y = *x;
I agree with you. using references as just an alias name is not very useful.
It is more useful if you consider it as an immutable pointer. But not that useful in fact.
Practically, it is used to define clean interfaces. For example when you define:
int foo(const int& param);
You say that param is a read-only parameter in foo.
Do not forget that you MUST assign a value to a reference.
See the C++ faqlite on references for more
my2c
References improve the syntax, so no pointer dereference needed.
Assuming Base is a class that may be derived from:
void someFunction(Base b)
{
b.function();
// b is a copy of what was passed - probably performance issues
// possible unintended object slicing - you only get the Base part of it
// no virtual function call
// no changes to b visible outside the function
}
void someFunction(Base* b)
{
b->function();
// a shortcut for (*b).function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
void someFunction(Base& b)
{
b.function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
References are like constant pointers (NOT pointers to constants - i.e. you can change the object, but you can't change to what you're pointing). const reference is a reference through which you can do things that can be done on const object.
References are also good, because you can't have a null reference
Give the wikipedia article a good read through. To sum it up, references are more friendly version of pointers which are commonly used to pass objects as references into functions without worrying about a null pointer.
To explain the example:
Think of the number 1 represented as a variable. When compiled, this number is put into the global section of the memory which can be referenced by the program, but not modified.
So it is of type: const int
double &dr = 1 is trying to assign dr (a reference to a double) to the const int 1. Since 1 is a constant, the compiler will not allow you to make a non-constant reference to it.
In the second line:
const double &dr = 1 is trying to assign dr (a constant reference to a double) the const int 1. This works because the reference is also const and therefore can point to a const int.
EDIT
The const int is converted to a const double before assigned.
References are language entitities that represent another object they refer to. Nonconst references are lvalues, and must be initialized with an lvalue. They can be useful like this:
int& x=condition ? array[1] : array[2];
int& y=condition ? array[0] : array[3];
x+=y;
y=0;
When used as a function parameter, they tell the caller he has to pass an lvalue that might be written to by the function:
void set1(int& x) { x=1; }
int foo;
set1(foo); // ok, foo is 1
set1(foo+1); // not OK, not lvalue
Const references, on the other hand, can be bound to rvalues. In function parameters, they are usually used to avoid excessive copies:
void niceness(std::string s); // the string would be copied by its copy-ctor
void niceness(const std::string& s); // the caller's string would be used
Note that this may or may not yield faster code.
When const-references are used in normal code, they can bind rvalues, too, and as a special rule, they extend the lifetime of the object they are bound to. This is what you saw in your code:
const double& d=1; // OK, bind a rvalue to a const-ref
double& d=1; // Bad, need lvalue
All references are polymorphic, like pointers:
class A { virtual void f(); }
class B : public A { void f(); }
B b;
A& ar=b;
ar.f(); // calls B::f()
and all references are aliases like pointers:
int f(int& a, const int& b)
{
a=1;
return b;
}
int x;
f(x, 42); // ==42, foo=1
x=42;
f(x, x); // ==1 (not 42), foo=1
double& dr = 1; // 1.0 would be more clear
Is invalid because 1 is viewed to be of type const double so if you want a reference to that variable you need to have a reference to a const double so
const double& dr = 1.0;
Is correct.
Utility of references is most visible in the context of passing parameters to functions.
I.e,
int a;
func definition: void foo (int& param) {param = 1;}
func call: foo(a);
The way as 'param' aliases 'a' is clean and its intention is easily understood by a reader of this code as well as compiler that may optimize away when inlining any additional memory allocation needed for the reference.
Passing a reference to a function and then having the function use the reference is almost like passing a pointer to the function and then having the function dereference the pointer. In many cases, the machine-code implementation will be identical. There are some differences, though, especially in the case of functions that get expanded inline. If a variable is passed by reference to an inline function, the compiler will often be able to substitute the variable itself--even if stored in a machine register--when expanding the function. By contrast, if one takes the address of a variable and passes that as a pointer to a function which then dereferences it, the compiler is less likely to figure out that optimization unless it determines not only that--at least for one particular expansion of the function--the pointer will always point to that variable, but also that the pointer will not be used anywhere else (if the pointer was used elsewhere, the variable could not be kept in a register).