This question already has answers here:
pass reference to array in C++
(3 answers)
Closed 8 years ago.
I want to pass value of array in function by reference
My first try with variable (it works well):
#include <iostream>
using namespace std;
int input(int &);
int main()
{
int a;
input(a);
cout << "the value : " << a << endl;
system("pause");
return 0;
}
int input(int &a)
{
cin >> a;
}
But when i change a to a[] like in the following code, it
doesn't work
#include <iostream.h>
using namespace std;
int input(int &[]);
int main()
{
int a[2], i;
input(a);
for(i=0;i<=2;i++)
{
cout << a << endl;
}
system("pause");
return 0;
}
int input(int &a[])
{
int i;
for(i=0;i<=2;i++)
{
cin >> a[i];
}
}
It should be:
void input(int (&a)[2]);
or simply
void input(int (&)[2]);
But in function definition, you need also to give the array name:
void input(int (&a)[2]) {...}
You need to use (&array) to clarify to the compiler that you want a reference to an array, rather than the (invalid) array of references int &array[2];.
And call it like this:
input(a);
This record
int &[]
denotes an array of references that is forbided in C++.
Declare the function the following way
void input( int ( & )[2] );
Also you are using invalid range of indeces. The valid range is [0, 1]. So the function will look as
void input( int ( &a )[2] );
{
for ( size_t i = 0; i < 2; i++ ) std::cin >> a[i];
}
Also you could define the function the following way
void input( int a[], size_t n );
{
for ( size_t i = 0; i < n; i++ ) std::cin >> a[i];
}
and call it as
input( a, 2 );
The syntax for returning and taking array references is:
template<typename T, size_t N>
T(&do_nothing(T(&arg)[N]))[N]
{
return arg;
}
Or, more simply with a templated type alias:
template<typename T, size_t N> using arrayref = T(&)[N];
template<typename T, size_t N>
arrayref<T, N> do_nothing(arrayref<T, N> arg)
{
return arg;
}
When you have defined the previous type alias template, it becomes very simple to work with array references, e.g. This is how you would declare a function that takes a reference to an array of two integers:
void give_me_two_ints(arrayref<int, 2> two_ints);
To be used like:
int a[] = {1,2,3};
for(auto const& i : do_nothing(a)) std::cout << i << "\n";
Related
I am learning c++ and facing some some difficulties in writing some code like how can we count the number of elements of an array through a function suppose we are not passing the variable for size ![enter image description here][1]
#include <iostream>
using namespace std;
void check(int arr[], int s);
int main ()
{
int array[5]={1,2,3,4,5};
check(array,5);
}
void check(int arr[], int s)
{
for (int i = arr[0]; i <= arr[s]; i++)
{
s=arr[s];
}
cout<<"size is : "<<s<<endl;
}
You use a template, and take a deduced array by reference instead of a pointer
template <size_t N>
void check(int (&)[N])
{
std::cout << "Size is : " << N << std::endl;
}
You can do it like
int size = sizeof(array)/sizeof(array[0]);
I was studying for my C++ exam and noticed that my answer differs from the solution. The question was to write a method that gives the biggest double or string (by size) from an array with templates. I know that by passing the array as a parameter you give a pointer to the first index.
I'm really confused on where I should write the "const" to signify that the array is not being altered though. Also the code contains 2 dutch words, "grootste" means "biggest", and "grootte" just means "size". PS: max= maximum
this is my solution:
#include <iostream>
using namespace std;
template <typename T>
T grootste(T const [],int);
double grootte(double);
int grootte(const string&);
int main(){
double getallen[5] = {5.5,7.7,2.2,9.8,9.9};
string woorden[3] = {"geloof","hoop","de liefde"};
cout << "Biggest number " << grootste(getallen,5) << "." << endl;
cout << "Longest of 3 strings " << grootste(woorden,3) << "." <<
endl;
return 0;
}
int grootte(const string &a){
return a.size();
}
double grootte(double d){
return d;
}
template <typename T>
T grootste (T const arr[], int lengte){
T max=arr[0];
for(int i=1;i<lengte;i++){
if(grootte(arr[i])>grootte(max)){
max = arr[i];
}
}
return max;
}
this is the solution my course gives me, there was no main included and the other methods were the same.
I wrote the solution again but now it's a literal copy from the pdf the students recieved. I'm sorry for the spacing, i have no idea why it does that.
template < class T >
T grootste ( const T * array , int lengte ){
T gr = array [0];
for ( int i =1; i < lengte ; i ++) {
if ( grootte ( gr ) < grootte ( array [i ]) ){
gr = array [i ];
}
}
return gr ;
}
These parameters are all equivalent:
const T p[]
T const p[]
const T *p
T const *p
Which one to choose is a matter of taste and convention.
I always get confused when types get complex. Use a typedef/using statement to make it clear what you mean exactly.
using intptr = int*; //pointer to int
void foo(const intptr arr ) { // a const pointer to int
arr[0] = 32;
// arr = nullptr; //This will fail
}
using cint = const int;
void bar(cint* arr){ // pointer to const int
//arr[0] = 42; //This will fail
arr = nullptr;
}
template<class T>
struct Types {
using Tptr = T*;
using ConstT = const T;
};
template<class T>
T grootste(typename Types<T>::constT* arr, int length) { //pointer to const T, i.e Ts in the array cannot change
//...
}
I can't identify my mistake. I need to create a function int search (int *p, int s, int n) that will search the array for target, and if found it it will return the adress yet if not found it will return NULL;
#include <iostream>
using namespace std;
int search(int *p , int s, int n)
{
for(int i = 0; i < s; i++)
{
if(*p == n)
return &p;
p++;
}
return NULL;
}
int main()
{
int n;
int arr[6] = {1, 2, 3, 4, 5, 6};
cout << "Enter target: "<< endl;
cin >> n;
cout << search(arr, 6, n) << endl;
return 0;
}
You are almost there:
return &p;
This is the issue that you are experiencing: You are returning address of a local pointer that you use for iterating over the input array.
Since you have used if(*p == n) in your code I would suppose that you have been aware that p is a pointer already. Then, once found the element you should simply return it right away:
return p;
Returning &p is definitely an error. p is a function parameter, and its life does not extend past the end of its function. In common implementation it resides in the stack and vanishes at return time, or more exactly can be overwritten at any time after the function returns.
But you do not need that. If you want an integer index, you need:
return i;
and if you really want an address, you should have:
int* search ( int *p , int s, int n) // returns an int* not an int
{
for(int i = 0; i<s;i++)
{
if(*p==n)
return p;
p++;
}
return NULL; // you should return a defined value if not found
}
#include <iostream>
#include <memory>
#include <algorithm>
#include <vector>
void findItemInVec(std::vector<int> &v ,int number) {
std::for_each(v.begin(), v.end(), [number](int &item_in_vec) ->void {
if (item_in_vec == number) {
std::cout << &item_in_vec << std::endl;
}
});
}
int main()
{
std::vector<int> v{ 1,2,5,8,7,6,1 };
findItemInVec(v, 1);
return 0;
}
The argument in the function is a vector of integer values. The function std::for_each checks every item inside the vector with the iterators help and checks if it has the same value with the number argument. For every check that returns true, it types the address of this item.
For example, I want to display value of only one member of structure/union array, so I want to pass it as argument into a function that will display only that one member and will also display any other single member that I pass as argument.
#include <iostream>
using namespace std;
union ThreeTypes
{
char letter;
int whole;
double real;
};
void showArr(ThreeTypes[], int); // ?? What parameters to pass?
int main()
{
const int SIZE = 50;
ThreeTypes arr[SIZE];
for (int i = 0; i < SIZE; i++)
arr[i].real = 2.37;
showArr(arr, SIZE, ??? ); // what argument to pass to display member?
return 0;
}
void showArr(ThreeTypes arr[],int size,???) // also, what parameters??
{
for (int i = 0; i < size; i++)
cout << arr[i].?? << endl; // member from argument????
}
One option would be a templated pointer-to-member type. These are usually used with class or struct types, but are also valid with a union type. A pointer-to-member type is declared like MemberType ClassType::*pointer_name, and the name of such a pointer can be used to the right of the .* or ->* operator.
template <typename T>
void showArr(const ThreeTypes arr[], int size, T ThreeTypes::*ptr)
{
for (int i = 0; i < size; ++i)
std::cout << (arr[i].*ptr) << std::endl;
}
And you create a pointer-to-member value with the syntax &ClassType::member_name:
int main()
{
const int SIZE = 50;
ThreeTypes arr[SIZE];
for (int i = 0; i < SIZE; i++)
arr[i].real = 2.37;
showArr(arr, SIZE, &ThreeTypes::real);
}
Another more general option would be to take a callable functor:
template <typename F>
void showArr(const ThreeTypes arr[], int size, const F& func)
{
for (int i = 0; i < size; ++i)
std::cout << func(arr[i]) << std::endl;
}
You can create a functor to access a member using a lambda or std::mem_fn:
void print_reals_twice(const ThreeTypes arr[], int size)
{
showArr(arr, size, [](const ThreeTypes& u) { return u.real; });
// Same effects:
showArr(arr, size, std::mem_fn(&ThreeTypes::real));
}
But defining showArr this way also lets you pass a functor that does something more complicated than just return a member, if you wanted:
void print_sin2x_all(const ThreeTypes arr[], int size)
{
showArr(arr, size, [](const ThreeTypes& u) { return std::sin(2*u.real); });
}
In C++17 you should use std::variant:
using ThreeTypes = std::variant<char, int, double>;
template <std::size_t N>
auto show_arr(std::array<ThreeTypes, N>& arr)
{
for (auto& e : arr)
{
std::visit([](auto e) { std::cout << e << std::endl;}, e);
}
}
auto test()
{
std::array<ThreeTypes, 2> arr = {3.4, 'a'};
show_arr(arr);
}
Why can't use nullptr in the constructor function?( the function name: Wine) When i try to do this, the program will break down and no any error report maybe because i don't the reason for that.
#ifndef WINE_H_
#define WINE_H_
#include<iostream>
#include<string>
#include<valarray>
using std::string;
using std::valarray;
template<typename T1, typename T2>
class Pair //member of the wine
{
private:
T1 a;
T2 b;
public:
T1 & first(){ return a; }
T2 & second(){ return b; }
T1 first()const{ return a; }
T2 second()const{ return b; }
Pair(const T1 & aval, const T2 & bval) :a(aval), b(bval){}
Pair(){}
};
typedef valarray<int>ArrayInt;
typedef Pair<ArrayInt, ArrayInt>PairArray;
class Wine
{
private:
string name;
PairArray bt;
int years;
public:
Wine();
Wine(const char * a, int y,int b[], int c[]); //no problem
Wine(const char * a, int y); //here is that problem function
void GetBottles(); //no problem
void Show()const; //no problem
int Sum(){ return bt.second().sum(); }
};
Wine::Wine(const char * a, int y) :name(a), years(y), bt(ArrayInt(0, y), ArrayInt(0, y)){}
**//When I am trying to use nullptr to instead 0 in the ArrayInt(0,y),the whole program will break down during work.**
Wine::Wine(const char * a, int y, int b[], int c[]) :bt(ArrayInt(b, y), ArrayInt(c, y))
{
name = a;
years = y;
}
Wine::Wine() :bt(ArrayInt(),ArrayInt())
{
name = "null";
years = 0;
}
void Wine::GetBottles()
{
std::cout << "Please input the years and the bottles\n";
for (int i = 0; i < years; i++)
{
std::cout << "input the year: ";
(std::cin >> bt.first()[i]).get();
std::cout << "input the bottles";
(std::cin >> bt.second()[i]).get();
}
}
void Wine::Show()const
{
using std::cout;
using std::endl;
for (int i = 0; i < years; i++)
{
cout << bt.first()[i] << '\0' << bt.second()[i] << endl;
}
}
#endif
#include<iostream> //test part
#include"wine.h"
int main(void)
{
using std::cin;
using std::cout;
using std::endl;
cout << "Enter name of wine: ";
char lab[50];
cin.getline(lab, 50);
cout << "Enter number of years: ";
int yrs;
cin >> yrs;
Wine holding(lab, yrs);
holding.GetBottles();
holding.Show();
return 0;
}
Thank your for your help!
This is a funny one. The reason why it breaks in one example, but not another is following:
There are two different constructors for std::valarray (more than that, but those two matter):
valarray( const T& val, std::size_t count ); // 1
valarray( const T* vals, std::size_t count ); // 2
When you use 0 (valarray(0, y)) you are calling the first version - creating an array of y elements, where every element is initialized to 0.
But when you are calling it with nullptr, you are calling the second version of it - trying to initialize your new array with a copy from an array pointed to by the first argument to the constructor. But your first argument is nullptr, and any attempt to use at as an array triggers undefined behavior, and program crashes.