Why "&" is needed during calling this list? - c++

I was studying LISTs and playing with function, this program gives 10 number and each time if the entered number is the bigger than the maximum value in our list, that number will be added to our list and finally after 10 tries all members will show up. The program works fine, but what I don't understand is why do I need use "&" in the line 6: " void insertMax(list &lst, int n) {"??
#include <iostream>
#include <list>
using namespace std;
void insertMax(list<int> &lst, int n) {
lst.sort();
int max = lst.back();
if (n > max) {
lst.push_back(n);
}
}
void disply(list<int> lst) {
list<int>::iterator iter = lst.begin();
while (iter!=lst.end()){
cout << *iter << endl;
iter++;
}
}
int main()
{
list<int> numbers;
numbers.push_back(0);
int input=0;
for (int j = 1; j < 11; j++){
cout << "Enter a number: " << endl;
cin >> input;
insertMax(numbers, input);
}
cout << "Now that's all: " << endl;
disply(numbers);
return 0;
}
Thanks in advance.

So you pass a reference to the list rather than a copy of it.
Google "pass by reference" and "pass by value".
Pass by reference means you don't have to make a copy of the whole data structure you are passing (which could be slow - especially if you have a big list)
Having said that, you're question is not quite clear: "Why is & needed during calling this list?" - Line 6 is not a call, it's the declaration of the function signature. So it's saying "When you call me I expect you to pass a reference to a list of ints"

By putting the ampersand (&) in, you specify that the list be taken as a reference, instead of being copied into the function scope. By taking it as a reference you can manipulate the external object.
http://www.cprogramming.com/tutorial/references.html

If I have understood correctly the line 6 is the starting line of the function definition
void insertMax(list<int> &lst, int n) {
lst.sort();
int max = lst.back();
if (n > max) {
lst.push_back(n);
}
}
Symbol & in the first parameter declaration means that the parameter will be a refence to the original argument. So any changes of the list in the function impact on the original argument.
If to remove this symbol & as for example
void insertMax(list<int> lst, int n) {
//...
the it will mean that the function will deal with a copy of the original argument. In this case any changes of the parameter that is pf the copy of the argument will not impact the original argument.
So the new item will be added to a copy of the list but the list itself will not be changed. It is its copy that will be changed.

If you don't add the '&' (pass by reference), any changes you make to the List inside the InsertMax function will not impact the list in your main method.
This is the reason why you'll sometimes see C++ method signatures declared as
void DoSomething(const std::string &value)
{
/*Method Body*/
}
This is done so all that data in the value string is not copied to a new place in memory. If the DoSomething method needs to modify the value string, it will need to make a copy of it first inside of the function. The const modifier makes sure that the reference is read-only by the method.
For example:
std::string DoSomething(const std::string &value)
{
std:string result = value + "some other data";
return result;
}

Related

Passing class with array member into overload of function that uses that array member

I'm trying to implement a polynomial class consisting of an int (degree) and an integer array (the coefficients for each term). I have a function to print the polynomial, which works fine when I pass in the degree and term array directly, but things get funky when I try to put those values into an instance of my polynomial class.
I am using variadic arguments in the polynomial's constructor, such that you should be able to call polynomial(degree, ). I made sure to output each term in my va_list so I know I'm targeting what I want to.
Here's my class:
class polynomial{
public:
polynomial(int degree...){
va_list args;
_degree = degree;
int p[degree];
va_start(args,degree);
for(int i = 0; i < degree; i++){
p[i] = va_arg(args,int);
cout << p[i] << endl; //just to verify that I'm grabbing the right values.
}
va_end(args);
_terms = p;
}
int degree(){return _degree;}
int* terms(){return _terms;}
private:
int _degree;
int* _terms;
};
And here's the function(s) I'm using to print the polynomial:
void printArray(int*p, int l){
std::cout << "[";
for(int i = 0; i < l; i++){
std::cout << p[i];
if(i != l-1) std::cout << ",";
}
std::cout << "]" << std::endl;
}
void printArray(polynomial p){
printArray(p.terms(), p.degree());
}
my main function:
int main()
{
int a[3] = {2,5,3};
printArray(a,3);
polynomial p1(3,2,5,3);
printArray(p1.terms(), p1.degree());
printArray(p1);
return 0;
}
and the output:
[2,5,3]
2
5
3
[2,0,94004573]
[1,0,1]
As you can see, I call printArray() 3 times. The first time, I directly create an integer array and pass it and its length into printArray(). This time, it works fine, outputting [2,5,3] as expected. The second time, I again use the first implementation of printArray(), but this time I pass in the int* and int from an instance of my polynomial. This time, I get some array whose first two elements always seem to be 0 and 2 and whose last value is some garbage value.
The third time, I simply pass in the polynomial to the second implementation of printArray(). This seems to output [1,0,1] consistently (which is of course incorrect).
I suppose it wouldn't be too confusing if the second and third calls to printArray() generated the same garbage values, but as it stands, I am fairly lost in terms of what's happening behind the scene. Any help at all would be appreciated. Thank you!
The problem is these two lines:
int p[degree];
and
_terms = p;
The first (besides not being a non-portable variable-length array extension of your compiler) defined p to be a local variable.
The second line makes _terms point to the first element of this array.
Then the constructor ends, and the life-time of p with it, leaving you with an invalid pointer in _terms.
The natural solution is to use std::vector instead. And if you need to use pointers (because assignment/exercise requirements) you need to use dynamic allocation (using new[], and also then you need to learn about the rule of three/five).

Why can't functions change vectors when they can change arrays?

I am trying to move from arrays to vectors in cpp for problem-solving and its overall benefits. I am facing some issues here even though this logic works on arrays.
#include <iostream>
#include <vector>
using namespace std;
void PrintArray(vector<int> v) { // O(n)
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
void LF1(vector<int> A) { // O(n)
int temp = A[0],i;
for (i=0; i<A.size()-1; i++)
A.at(i) = A.at(i+1);
A.at(i)=temp;
// PrintArray(A); <-- shows updated array here
}
void LF(vector<int> A, int d) {
d = d % (A.size());
cout << "d%n: " << d << endl;
for (int j=0; j<d; j++)
LF1(A);
PrintArray(A);
}
int main(int argc, char const *argv[]) {
vector<int> A;
int d;
for(int i=1; i<6; i++)
A.push_back(i);
PrintArray(A);
cout << "Enter number of Left rotations to perform : ";
cin >> d;
LF(A,d);
return 0;
}
Problem 1: When I am calling LF1 inside of LF it returns the same array without rotating but when I write the code for LF1 inside of LF it seems to rotate.
Problem 2: The PrintArray() prints the rotated array only when called from LF1() or just immediately after its code when written (instead of calling LF1()) in LF() when causes it to print the array d times. Where d is the required rotations.
Regarding what you're doing wrong...you are passing the vectors by value. You don't expect changes to an integer to affect it in the caller when you pass it as a value...
void SomeFunction(int i) {
i = i + 1;
printf("Inside SomeFunction %d\n", i); // changed, 11
}
int i = 10;
SomeFunction(i);
printf("Outside SomeFunction %d\n", i); // unchanged, 10
...if you wanted to see a change, you would have to pass a pointer, such as int *pi, and then update it as *pi = *pi + 1;
The same principle applies to vectors and other C++ classes. If you just pass it as a value, the whole vector is copied. (Well, if it needs to be, a temporary could just be reused). But for now think of it as being copied: just as there's a difference between passing an integer and a pointer-to-an-integer, there's a difference between a vector and a pointer-to-a-vector.
You could pass a pointer to the vector if you intend to change it...or... C++ offers another tool called the reference, where references are very much like pointers but with a few differences. If you just changed your arguments to vector<int> &A then your code should work, because the arrays would be "passed by reference" instead of getting copied when they are "passed by value", so changes would take effect. If you don't want a function to need to be able to modify an array but still want to avoid the copy, pass by const reference, e.g. const vector<int> &A (e.g. this is what your PrintArray() should use).
You might not want to get too hung up on the details of references for now, other than thinking of it as a "convenient kind of pointer where you don't have to put the * on all the places you want to dereference". But in case you want to know more specifics:
What are the differences between a pointer variable and a reference variable in C++?
I am facing some issues here even though this logic works on arrays.
And this is probably the source of your confusion. Which comes from the fact that C-style arrays decay into pointers under the hood:
Passing an Array by reference in C
I think that's something that it's reasonable to be confused by, given that other types (such as integers and vectors) don't. It's just a quirk of C, that C++ inherited. So when C++11 wanted to clean that up, a wrapper class called std::array was introduced:
https://embeddedartistry.com/blog/2017/6/28/an-introduction-to-stdarray
https://en.cppreference.com/w/cpp/container/array
But C++ also has an algorithm to do rotation...
So if you want to see a good example of how this would be done, it's a place to start:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> v{1, 2, 3, 4};
std::rotate(v.begin(), v.begin() + 1, v.end());
for (auto &i : v)
std::cout << i << " ";
std::cout << "\n";
}
That will get you 2 3 4 1. The documentation has other examples, read through:
https://en.cppreference.com/w/cpp/algorithm/rotate

How to use an array of pointers to functions?

I want to use for example this array of pointers to functions, without using STL.
That array is an array of pointers that I call functions OptionA, OptionB and so on.
int(*Functions[4])();
Functions[0] = OpionA;
Functions[1] = OptionB;
Functions[2] = OptionC;
Functions[0] = Exit;
Now if I write inside the function where I have my array
Functions[0];
I want to have called function 'OptionA' where it has been defined before for example like this:
int OptionA()
{
cout << "OPTION A";
_getch();
return 0;
}
Is it possible to do this without STL?
If not, I would like to know how to do it with STL.
You can create and pass arrays of function pointers like any other types. It's easiest if you have a type alias (my example leverages using, but typedef will also work).
#include <iostream>
using Function = int (*)(int, int);
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
void do_stuff(int a, int b, Function * fns, int cnt) {
for(auto i = 0; i < cnt; ++i) {
std::cout << "Result " << i << " = " << fns[i](a, b) << '\n';
}
}
int main() {
Function fns[2] = { add, sub };
do_stuff(10, 7, fns, 2);
return 0;
}
Output:
Result 0 = 17
Result 1 = 3
I think that what you are looking for is
How to initialize a vector of pointers
Once your vector is initialize you can send it to a function like a normal data type.
Example:
std::vector<int*> array_of_pointers{ new int(0), new int(1), new int(17) };
function(array_of_pointers);
In the declaration of the function
void function(std::vector<int*> array_of_pointers);
I hope this answer your question.
In C and C++, arrays are second-class. They cannot be passed by value by themselves, only if somehow wrapped.
As a first step, the questions you have to decide are:
Does your array have a fixed length?
And do you have to pass it by value or can you pass it by reference?
If you have to pass it by value, is that a choice you want the caller to make, or the callee to impose? In the first case, pass it by reference.
If you pass the array by reference, nothing can beat using a gsl::span, unless you pass multiple sequences all having intrinsically the same length, in which case passing pointers and a single length-argument is more efficient and maybe comfortable.
If you pass an array of variable length by value, try to use a std::vector. That's also the go-to type to pass a by-ref argument as if by-value.
Otherwise (array of fixed length, by value), nothing beats std::array.
If p is a pointer to a function, which receives no parameters, you should call it by this syntax:
p();
So, if array is an array of pointers to functions, you should call one of them using the same syntax idea:
array[0]();
Here the parentheses are important; they say "call this function, and pass no parameters to it". If you have no parentheses
array[0];
this means "select this function from the array, but do nothing with it".
It's a useless expression, like if you have an integer x, then x * 5 means "multiply x by 5 and do nothing with the result" (useless), while x *= 5 means "multiply x by 5 and replace x with the result".

Need help in understanding the below c++ code

#include<iostream>
using namespace std;
int number(int (&a)[10])
{
int n= sizeof(a)/sizeof(a[0]);
return n;
}
int main()
{
int n;
cout << " Enter the number of elements ";
cin >> n;
int a[10];
cout << "Enter array elements : ";
for(int i=0;i<n;i++)
cin>>a[i];
cout<<" The number of elements according to main is "<< sizeof(a)/sizeof(a[0])<<endl;
cout<<" The number of elements in the function number is " << number(a);
}
In the above code in the main function "number(a)" Here what exactly are we passing and what is taken by the method. and how does the code work in the function.and what is happening if we are not using "&" symbol in the number function.
My understanding is we are passing a pointer to the first element into the function but I dont know properly.
When you call number(a), you are passing a reference to the array of 10 ints.
Let's take a simpler function.
void foo(int& ref) { }
You can call it with
int i = 20;
foo(i);
Here, a reference to the variable i passed to the function. You can access the value of the variable i in foo through ref. Any changes you make to ref in foo will be visible in the calling function.
Similarly, your function takes a reference to a variable whose type is "an array of 10 ints". The only thing the function does with the reference is compute the number of elements of the array.
It uses a bit of redundant logic. You can simplify that function to:
int number(int (&a)[10])
{
return 10;
}
The function is limited in what it can work with. It is not going to work if you have an array of type float or if you have an array of 20 elements. You can create a template function to make it more general.
template <typename T, size_t N>
size_t number(T (&arr)[N])
{
return N;
}
The above function will work with arrays of different object types and sizes.

C++ Passing array into function

I'm relatively new to C++ and am having a tough time passing my array into a separate function. Apologies for re-asking a question that has no doubt been answered a dozen times before, but I couldn't find any questions similar to the problem I have with my code.
int main()
{
Array<int> intarray(10);
int grow_size = 0;
intarray[0] = 42;
intarray[1] = 12;
intarray[9] = 88;
intarray.Resize(intarray.Size()+2);
intarray.Insert(10, 6);
addToArray(intarray);
int i = intarray[0];
for (i=0;i<intarray.Size();i++)
cout<<i<<'\t'<<intarray[i]<<endl;
Sleep(5000);
}
void addToArray(Array<int> intarray)
{
int newValue;
int newIndex;
cout<<"What do you want to add to the array?"<<endl;
cin >> newValue;
cout<<"At what point should this value be added?"<<endl;
cin >> newIndex;
intarray.Insert(newValue, newIndex);
}
You are passing a copy of the array, so any changes will not affect the original. Pass by reference instead:
void addToArray(Array<int> &intarray)
// ^
This is a special case of a more general question on parameters passing.
You may want to consider the following guidelines:
If you want to pass something to a function to modify it inside the function (and make the changes visible to the caller), pass by reference (&).
e.g.
// 'a' and 'b' are modified inside function's body,
// and the modifications should be visible to the caller.
//
// ---> Pass 'a' and 'b' by reference (&)
//
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
If you want to pass something that is cheap to copy (e.g. an int, a double, etc.) to a function to observe it inside the function, you can simply pass by value.
e.g.
// 'side' is an input parameter, "observed" by the function.
// Moreover, it's cheap to copy, so pass by value.
//
inline double AreaOfSquare(double side)
{
return side*side;
}
If you want to pass something that is not cheap to copy (e.g. a std::string, std::vector, etc.) to a function to observe it inside the function (without modifying it), you can pass by const reference (const &).
e.g.
// 'data' is an input parameter, "observed" by the function.
// It is in general not cheap to copy (the vector can store
// hundreds or thousands of values), so pass by const reference.
//
double AverageOfValues(const std::vector<double> & data)
{
if (data.empty())
throw std::invalid_argument("Data vector is empty.");
double sum = data[0];
for (size_t i = 1; i < data.size(); ++i)
sum += data[i];
return sum / data.size();
}
In modern C++11/14 there is also an additional rule (related to move semantics): if you want to pass something that is cheap to move and make a local copy of it, then pass by value and std::move from the value.
e.g.
// 'std::vector' is cheap to move, and the function needs a local copy of it.
// So: pass by value, and std::move from the value.
//
std::vector<double> Negate(std::vector<double> v)
{
std::vector<double> result( std::move(v) );
for (auto & x : result)
x *= -1;
return result;
}
Since in your addToArray() function you modify the Array<int> argument, and you want modifications visible to the caller, you can apply rule #1, and pass by reference (&):
void addToArray(Array<int> & intarray)
My suggestion is use pointer, as usual declare the function
void yourFunction(int * arrayPointer);
In main() function you should input
int yourArray[8] = {11, -2, 45, 37, 18, 35};
int * arrayPointer = &yourFunction[0];
yourFunction(yourArray); // call your function
Finally in yourFunction()
void yourFunction(int * arrayPointer)
{
// print all number in the array
for(int x = 0; x < 6; x++)
{
cout << *arrayPointer << " ";
arrayPointer++;
}
}
This at least work for me, hope this will help