I want to pass array to function by reference. This function will dynamically allocate the elements.
This code give me an error message: access violation
#include <iostream>
using namespace std;
void func(int* ptr)
{
ptr = new int[2];
ptr[0] = 1;
ptr[1] = 2;
}
void main()
{
int* arr = 0;
func(arr);
cout << arr[0] << endl; // error here
}
C++ passes arguments by value. If you want to pass an int pointer by reference, you need to tell C++ the type is "reference to pointer to int": int*&.
Thus, your function prototype should be
void func(int*& ptr);
Note that you are still not handling pointers or references to arrays, but rather a pointer to the first element, which is close but not the same.
If you really wanted to pass an array of size 2 by reference, your function prototype would look like this:
void func(int(&my_array)[2]);
First of all function main shall have return type int.
As for your question then either you have to pass the pointer by reference or pass pointer to pointer. Or you could simply return pointer from the function.
Here is a demonstrative program that shows the three approaches. Take into account that you could use smart pointer std::unique_ptr.
#include <iostream>
int * func()
{
int *ptr = new int[2];
ptr[0] = 1;
ptr[1] = 2;
return ptr;
}
void func( int **ptr )
{
delete [] *ptr;
*ptr = new int[2];
( *ptr )[0] = 3;
( *ptr )[1] = 4;
}
void func( int * &ptr )
{
delete [] ptr;
ptr = new int[2];
ptr[0] = 5;
ptr[1] = 6;
}
int main()
{
int *arr = func();
std::cout << arr[0] << ", " << arr[1] << std::endl;
func( &arr );
std::cout << arr[0] << ", " << arr[1] << std::endl;
func( arr );
std::cout << arr[0] << ", " << arr[1] << std::endl;
delete [] arr;
}
And one more example of using std::unique_ptr
#include <iostream>
#include <memory>
std::unique_ptr<int[]> func()
{
std::unique_ptr<int[]> p( new int[2] );
p[0] = 1;
p[1] = 2;
return p;
}
void func( std::unique_ptr<int[]> &p )
{
p.reset( new int[2] );
p[0] = 3;
p[1] = 4;
}
int main()
{
std::unique_ptr<int[]> p = func();
std::cout << p[0] << ", " << p[1] << std::endl;
func( p );
std::cout << p[0] << ", " << p[1] << std::endl;
}
As you see in this case you need not bother about calling operator delete []
Related
I have tried this piece of code mentioned below, I'm not understanding why *p need to be pass to doOperation() function. Why can't we pass p? What is the difference between the two?
doOperation(*p); // need explanation why derefencing
doOperation(p); // Gives compilation error
int main()
{
int *p = getpointer();
std::cout << "p:" << *p << std::endl;
doOperation(*p); // Why this has to be pass as a pointer when the function parameter as reference
return 0;
}
void doOperation(int &ptr)
{
//std::cout << "ptr:" << ptr << std::endl;
}
int *getpointer()
{
int *ptr = new int[10];
int i;
for (i=0; i <= 10; i++)
{
*(ptr+i) = i;
}
return ptr;
}
You've declared p as an integer pointer. The function doOperation takes an int reference as a parameter. doOperation(*p) means that you're dereferencing the pointer (which points to the first element in the array) and passing it to the function. Also as #dxiv have pointed out, in the function getpointer, the loop initializes 11 elements instead of 10. you can solve this by just changing <= to <.
If you want to pass the pointer by reference instead, the function doOperation can look like this:
void doOperation(int *&ptr)
{
std::cout << "ptr:" << ptr << std::endl;
}
Then you can just pass the pointer as an argument like this:
doOperation(p);
Output:
p:0
ptr:0x2b71550
The code after the changes should look like this:
#include <iostream>
void doOperation(int *&ptr)
{
std::cout << "ptr:" << ptr << std::endl;
}
int *getpointer()
{
int *ptr = new int[10];
int i;
for (i=0; i < 10; i++)
{
*(ptr+i) = i;
}
return ptr;
}
int main()
{
int *p = getpointer();
std::cout << "p:" << *p << std::endl;
doOperation(p);
return 0;
}
I want to pass a double pointer as argument to a function, but I cant see what I am doing wrong.
#include <iostream>
#include <string>
using namespace std;
void changeString(string ***strPtr) {
strPtr = new string**[1];
*strPtr = new string*[1];
**strPtr = new string("hello");
//cout << strPtr[0][0][0];
}
int main()
{
string **strPtr;
changeString(&strPtr);
//cout << strPtr[0][0];
return 0;
}
The cout in changeString works fine, but the cout in main throws the exception read access violation. strPtr was 0xCCCCCCCC.
Your example is basically equivalent to this:
void changeString(string **strPtr) {
strPtr = new string*[1];
*strPtr = new string("hello");
//cout << strPtr[0][0];
}
int main()
{
string *strPtr;
changeString(&strPtr);
//cout << strPtr[0];
return 0;
}
And that is basically equivalent to this:
void changeString(string *strPtr)
{
strPtr = new string("hello"); // Changes the pointer, not the string!
//cout << strPtr[0];
}
int main()
{
string str;
changeString(&str);
//cout << str;
return 0;
}
At this point it should start to become obvious that you are assigning a new value to the pointer, not the pointed-to object. Consider this:
void change(SomeType t)
{
t = somethingElse;
}
int main()
{
SomeType t;
change(t); // Does not change t.
}
In your case, SomeType happens to be string* (or string***) - you are just overwriting a local variable.
To fix your code, just skip the first line in changeString:
http://coliru.stacked-crooked.com/a/88874ee3601ef853
void changeString(string ***strPtr)
{
*strPtr = new string*[1];
**strPtr = new string("hello");
cout << strPtr[0][0][0];
}
int main()
{
string **strPtr;
changeString(&strPtr);
cout << strPtr[0][0];
return 0;
}
Here I want to get rid of insert function by overloading [] and = operators.
By overloading [] operator, I have successfully returned the address of the required location where I want to insert the value.
#include<iostream>
using namespace std;
#define const maxSize = 30;
class ARRAY
{
private:
int *ar;
int end;
public:
ARRAY()
{
ar = new int[40];
end = -1;
}
void insert(int value)
{
end += 1;
ar[end] = value;
}
void insert(int value, int index)
{
if (index<30 && index >-1)
{
int tempEnd = end;
for (int i = end; i >= index; --i)
{
ar[tempEnd + 1] = ar[tempEnd];
tempEnd -= 1;
}
end += 1;
ar[index] = value;
}
else
cout << "\nOVERFLOW";
}
void remove(int index)
{
if (index >= 0 && index <= end)
{
for (int i = index; i < end; ++i){
ar[i] = ar[i + 1];
}
end -= 1;
//do something
}
else
cout << "\nNothing gonna happens";
}
void display()
{
for (int i = 0; i <=end; ++i)
cout << "\n" << ar[i];
}
int* operator[](int at)
{
if (at < 40){
end++;
return (&ar[at]);
}
}
//Here I want to do = operator overloading, How can I do this?
};
int main()
{
ARRAY arr;
arr.insert(1);
arr.insert(2);
arr.insert(3);
arr.insert(4);
arr.insert(5);
arr[5] = 10;
arr.display();
return 0;
}
You can achieve the desirable behavior by changing the return type of your operator[]:
int& operator[](int at)
In your original code it returns pointer to the array element, which, even if changed, does not do anything with the value stored in the array. With your original code, you could write something like this to change the element's value:
*(arr[5]) = 10;
which looks unobvious.
If you return reference instead of pointer, you can directly change the value it references to.
You do not need to overlaod the assignment operator '=' for your purpose. Only overload the access operator '[]'.
That should look something like this:
returntype& operator [](int indexvariable);
That is going to give you a reference to an instance of returntype and therefore you wont need to overload the assignment operator of your returntype in your case.
Then you can write:
arr[5] = 23;
You can achieve pretty much any desirable behavior with some trickery.
In your case, if you want some specific action for operator= (e.g. check bounds & insert a new element), you can introduce a helper class, that will hold a reference to an array and an index, and then overload the operator= for that class:
class ArrayIndex
{
ARRAY& array;
int index;
public:
ArrayIndex(ARRAY& a, int i) : array(a), index(i) {}
void operator=(int value)
{ array.insert(value,index); }
};
And of course you tweak your ARRAY's operator[] to return the ArrayIndex object.
If you don't want the insertion or any unusual actions, and only want to access the elements, then operator[] returning the reference (int&) will suffice.
Following the comment OP left on akexeykuzmin0's response, I suggest to alter your operator[] to return a handler to your element.
#include <iostream>
struct ARRAY
{
struct Handler
{
int* _ptr;
Handler(int* ptr) : _ptr(ptr) {}
int& operator*() { return *_ptr; }
operator int*() { return _ptr; }
int& operator=(int const& value) { *_ptr = value; return **this; }
};
int _value;
ARRAY(int n) : _value(n) {}
Handler operator[](size_t) { return Handler(&_value); }
};
int main() {
ARRAY arr(42);
std::cout
<< std::hex << &arr._value << "\n"
<< std::dec << arr._value << "\n"
<< *arr[0] << "\n\n";
arr[0] = 137;
std::cout
<< std::hex << &arr._value << "\n"
<< std::dec << arr._value << "\n"
<< *arr[0] << "\n\n";
int* pvalue = arr[0];
*pvalue = 0;
std::cout
<< std::hex << &arr._value << "\n"
<< std::dec << arr._value << "\n"
<< *arr[0] << "\n\n";
}
Output
g++ -std=c++17 -O2 -Wall -Werror main.cpp && ./a.out
0x7ffd682844f0
42
42
0x7ffd682844f0
137
137
0x7ffd682844f0
0
0
Live demo on coliru
This handler can be implicitly converted to a int* and you can overload the operator= on it.
Why is this code not valid?
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(beta);
}
Because beta is a pointer to int, but callbyreference doesn't take a pointer parameter - it takes a reference.
References are not pointers.
You can say either
void callbyreference (int* adam) {
cout << *adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(beta);
}
or
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int beta = 34;
callbyreference(beta);
}
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(*beta);
}
Why this code runs, VC++ will show a out of range exception?
error message:
vector Line:933
Expression: "Standard C++ Libraries Out of Range" & & 0
high is a function to return the highest element in an iterator. Then I construct an array and a vector, use high to find the highest element in them.
This is iterator.h:
template<class Iterator> Iterator high(Iterator first, Iterator last)
{
Iterator high = first;
for(Iterator p = first; p != last; ++p)
if(*high < *p) high = p;
return high;
}
This is main function:
#include <iostream>
#include <vector>
#include "iterator.h"
using namespace std;
double* get_from_jack(int* count)
{
double* p = new double[5];
p[0] = 2.3;
p[1] = 3.1;
p[2] = 2.1;
p[3] = 1.2;
p[4] = 4.3;
*count = 5;
return p;
}
vector<double>* get_from_jill()
{
vector<double> v;
v.push_back(2.1);
v.push_back(3.8);
v.push_back(5.1);
v.push_back(2.2);
v.push_back(1.9);
v.push_back(4.4);
vector<double>* p = &v;
return p;
}
void fct()
{
int jack_count = 0;
double* jack_data = get_from_jack(&jack_count);
vector<double>* jill_data = get_from_jill();
double* jack_high = high(jack_data, jack_data+jack_count);
vector<double>& v = *jill_data;
double* jill_high = high( &v[0], &v[0]+v.size() );
cout << "Jill's high " << *jill_high << "; Jack's high " << *jack_high;
delete[] jack_data;
delete jill_data;
//delete jack_high;
//delete jill_high;
}
int main()
{
try{
fct();
int n;
cin >> n;
return 0;
}
catch(exception&e)
{
cerr << e.what();
return 1;
}
catch(...)
{
return 2;
}
}
get_from_jill() returns a vector to a pointer that doesn't exist any more once the function is terminated.
You either have to instantiate the vector on the heap like you did it with the array, or return a copy of it. I would prefer the latter, it would make your code more concise.