C++ - fail to modify pointer in class member function - c++

I defined a function getArray() in class A, like this:
void getArray(int * arr){
arr = new int[10];
arr[0] = 1;
}
I want to modify pointer arr in getArray(). And I invoked function getArray() in main(), like this:
int main(){
A obj;
int * arr = new int[2];
obj.getArray(arr);
cout<<arr[0]<<endl;
delete[] arr;
}
But when I executed main(), the output of arr[0] is 0, not 1. Why?
Actually, I want to allocate new memory to pointer arr and set the contents of the array in function getArray(). Then I want to get the contents of the array and deallocate pointer arr in main(). But I don't know what to do.

The array was not modified, because you reassign the variable in getArray. This code will work:
void getArray(int * arr){
arr[0] = 1;
}
You should decide where the memory for array is allocated. If the answer is in main, then you should deallocate it at the end of this function:
int main(){
A obj;
int * arr = new int[2];
obj.getArray(arr);
cout<<arr[0]<<endl;
delete[] arr;
}
If the array should be created in getArray, then you don't need the allocation in main, and you should return the new pointer from getArray, and don't forget to deallocate it:
int * getArray(){
int * arr = new int[10];
arr[0] = 1;
return arr;
}
int main(){
A obj;
int * arr = obj.getArray();
cout<<arr[0]<<endl;
delete[] arr;
}

Because you are calling getArray with a copy of your pointer.
You can call functions by-value or by-reference. Using a pointer may look like a by-reference call, yet it is a by-value call as a pointer only stores a reference.
You could use pass the pointer by-reference to achieve what you are trying to do: void getArray(int *& arr).
BTW: I hope that this code isn't somewhere in a productive environment as it has 2 memory leaks.
UPDATE:
Examples using std::vector:
Example 1:
#include<iostream>
#include<vector>
struct A
{
void getData(std::vector<int>& v){
v = std::vector<int>(10, 0); //vector with 10 zeros
v[0] = 1;
}
};
void printData(const std::vector<int>& v)
{
std::cout << "v.size() = " << v.size() << std::endl;
for(int value : v)
{
std::cout << value << std::endl;
}
}
int main(){
A obj;
std::vector<int> v;
obj.getData(v);
printData(v);
return 0;
}
Example 2:
#include<iostream>
#include<vector>
struct A
{
std::vector<int> getData(){
std::vector<int> v(10, 0); //vector with 10 zeros
v[0] = 1;
return v;
}
};
void printData(const std::vector<int>& v)
{
std::cout << "v.size() = " << v.size() << std::endl;
for(int value : v)
{
std::cout << value << std::endl;
}
}
int main(){
A obj;
std::vector<int> v = obj.getData();
printData(v);
return 0;
}

Related

Why is the scope of object created using new limited? [duplicate]

This question already has answers here:
Do Pointer Parameters Need To Be Passed By Reference
(3 answers)
Closed 3 years ago.
Object made using new operator does not seem to be available outside the scope! Isn't that the whole point of the new operator?
https://ideone.com/DDvo9y - Please check this link to see the result.
#include<iostream>
class myClass
{
private:
int val;
public:
myClass () = delete;
myClass (int val):val{val}{}
int get () const
{
return val;
}
};
bool ifEqualMake (int a, int b, myClass * obj)
{
if (a == b) obj = new myClass (a);
else{
std::cout << "Difference exists: " << a - b << '\n';
obj = new myClass (a + b);
}
std::cout << " Object made with value :" << obj->get () << '\n';
return (a == b);
}
int main ()
{
myClass *obj1 = nullptr;
myClass *obj2 = nullptr;
myClass *obj3 = nullptr;
ifEqualMake (3, 3, obj1);
ifEqualMake (4, 3, obj2);
ifEqualMake (4, 4, obj3);
if(obj1) std::cout << "obj 1 made in heap: " << obj1->get () << '\n';
if(obj2) std::cout << "obj 2 made in heap: " << obj2->get()<<'\n';
if(obj3) std::cout << "obj 3 made in heap: " << obj3->get () << '\n';
delete obj1;
delete obj2;
delete obj3;
return 0;
}
It isn't.
You're confusing the dynamically-allocated object that you created with new, and the pointer that points to it.
The pointer's scope is limited just like any other automatic-storage-duration object.
It looks like you meant to use it as an "out" argument to the function ifEqualMake, perhaps by taking a reference to it rather than a copy. Then alterations to it, such as pointing it to a new object, will be mirrored in the calling scope.
The parameter obj is passed by value, that means it's just a copy of the argument, and any modification on itself inside the function (like obj = new myClass (a);) has nothing to do with the original pointer. In the meanwhile, the object constructed inside the function won't be destroyed.
You might change it to pass-by-reference.
bool
ifEqualMake (int a, int b, myClass *& obj)
// ^
{
...
}
Consider the following function:
void foo(int i) {
i = 4;
}
void bar() {
int j = 0;
foo(j);
std::cout << j << '\n';
}
You would expect bar to print 0, not 4, because foo is assigning to a local variable.
This behaviour does not change with pointers. The following code behaves the same way:
void foo(int* i) {
int temp = 0;
i = &temp;
}
void bar() {
int* j = nullptr;
foo(j);
std::cout << j << '\n';
}
The simplest fix to the code you present is to take the pointer by reference:
void foo(int*& i) {
int temp = 0;
i = &temp;
}
void bar() {
int* j = nullptr;
foo(j);
// j now points to a destroyed object
std::cout << j << '\n';
}

How to alloc array of pointers to functions usinig new?

Suppose I have a pointer to pointer to function taking int and returning int*.
int* (**ptr)(int) //i hope i'm not wrong here
How should I alloc memory for that pointer using new? And how can I create an array of pointers to functions with new?
I was trying something like this:
int* (**ptr)(int) = new int* (*)(int);
but it shows "expected primary-expression before ‘)’ token"
Here is a demonstrative program that shows how the array can be declared with a typedef and without a typedef.
#include <iostream>
int * func1(int value)
{
static int x = value;
return &x;
}
int * func2(int value)
{
static int x = value;
return &x;
}
int * func3(int value)
{
static int x = value;
return &x;
}
int main()
{
const int N = 3;
typedef int * (*PFunc)(int);
PFunc *ptr = new PFunc[N] { func1, func2, func3 };
int* (**ptr1)(int) = new ( int* (*[N])(int) ){ func1, func2, func3 };
for (int i = 0; i < N; i++)
{
std::cout << *ptr[i]( i ) << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < N; i++)
{
std::cout << *ptr1[i]( i ) << std::endl;
}
std::cout << std::endl;
return 9;
}
The correct syntax to create an array of functions pointers is as follows:
int* (**ptr)(int) = new (int*(*[5])(int));
This creates an array of 5 function pointers, where each function pointer is of type int *(*)(int).
This can be simplified with a typedef:
typedef int *(*fp)(int);
fp *ptr2 = new fp[5];

Whats the correct way of accessing the array through reference

How do i access the array in the main using the reference arrref
The memory leak in the code below is intended to know valgrind tool.But i am not able to compile the code below
#include <iostream>
int& func();
int main()
{
int &arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
int& func()
{
int *a = new int[10];
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return *a;
}
Thanks
The syntax needed is (&arrref)[1]. That refers to the second element of an array.
But make sure that the reference returned from func indeed refers to the first element of an array with sufficient number of elements.
To communicate clearly that func returns a reference to an array you may like to return a range, e.g.:
#include <iostream>
#include <boost/range/as_array.hpp>
boost::iterator_range<int*> func() {
static int array[2] = {1, 2};
return boost::as_array(array);
}
int main() {
auto array = func();
std::cout << array[0] << '\n';
std::cout << array[1] << '\n';
for(auto const& value: func())
std::cout << value << '\n';
}
Outputs:
1
2
1
2
Firstly it is not a good idea access local variables of one function in some other functions.
The function return type is int& which says that you want to return a reference to an int variable.
If you want to access the array local array 'a' then the function should be rewritten as -
#include <iostream>
int* func();
int main()
{
int *arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
int *func()
{
int *a = new int[10];
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return a;
}
Alternatively you can also use vectors -
#include<iostream>
#include<vector>
std::vector<int>& func();
int main()
{
std::vector<int>& arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
std::vector<int>& func()
{
std::vector<int> a(10);
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return a;
}

C/C++ Vector and reference parameter

I want to receive a VECTOR in my main function. The code is this.
int myfunction(void);
int main(){
int p = myfunction(void);
std::cout << p[2] << std::endl;
};
int myfunction(void){
int new array[4]={0,1111,2222,3333};
int *p;
p = array;
return p;
};
In C++ you would do:
std::vector<int> myfunction();
int main(){
std::vector<int> p = myfunction();
std::cout << p[2] << std::endl;
}
std::vector<int> myfunction(){
return std::vector<int>{0,1111,2222,3333};
}
And in C you could do:
int* myfunction(void);
int main(void){
int* p = myfunction();
printf("%d\n", p[2]);
free(p);
}
int* myfunction(void){
int tmp[] = {0,1111,2222,3333};
int* array = (int*)malloc(sizeof(tmp));
memcpy(array, &tmp, sizeof(tmp));
return array;
}
Now if you have trouble with this code, I'd recommend you go pick a good C or C++ book (whichever it is you're interested in) and read up on the basics of the language, because you seem really confused.

Const pointers shallow copy

is it possible to copy
MyStruct * const * array1
to
MyStruct * array1
but just as a shallow copy? I need sort it and write back into it and I want changes in array 1 too
EDIT: Im stupid, I overlooked ** at array1 then it makes sense.
I guess you mean const MyStruct * array1?
In any case you can use const_cast to change constness of a pointer:
const MyStruct * array1;
MyStruct * array2 = const_cast<MyStruct *>(array1);
Or
const MyStruct * const array1;
MyStruct * array2 = const_cast<MyStruct *>(array1);
Works for exactly the structure from the question... But, the second array1 replaced with another pointer parray.
Maybe, you qualify this as a deep copy even if it is a shallow copy of the struct?
Then, maybe, the other answer is better.
struct MyStruct {
int i;
int* p;
};
int j=2;
MyStruct st={ 1, &j };
int main() {
MyStruct* parray1(&st);
MyStruct* const* array1(&parray1);
MyStruct * parray=new MyStruct();
parray->i = (*array1)->i;
parray->p = (*array1)->p;
/*
This is essentially the same as
(*parray) = *(*array1);
*/
delete parray;
}
Edit: A second example as discussed in the comments to this answer.
Here we have a non-const pointer to which we successively assign the pointer values from the const pointer-pointer array1.
#include <iostream>
struct MyStruct {
int i;
int* p;
};
int j=2;
MyStruct st1={ 1, &j }, st2={ 2, &j };
int main() {
MyStruct* parray1[2] = {&st1, &st2};
MyStruct* const *array1(parray1);
std::cout << array1[0]->i << ' ' << array1[1]->i << '\n';
MyStruct* parray=array1[0];
parray->i = 3;
parray=array1[1];
parray->i = 4;
std::cout << array1[0]->i << ' ' << array1[1]->i << '\n';
return 0;
}
The corresponding output:
1 2
3 4
After the last comments (I think) we have reached a common interpretation of the question.
The pointers in the const array are to be copied into a non-const array where they can be re-arranged and the objects can be modified.
#include <iostream>
#include <algorithm>
struct MyStruct {
int i;
int* p;
};
int j=2;
MyStruct st1={ 1, &j }, st2={ 2, &j };
int main() {
MyStruct* parray1[2] = {&st1, &st2};
MyStruct* const *array1(parray1);
std::cout << array1[0]->i << ' ' << array1[1]->i << '\n';
MyStruct* parray[2];
std::copy(array1,array1+sizeof(parray)/sizeof(parray[0]),parray);
// some manipulation:
std::swap(parray[0],parray[1]);
parray[0]->i = 3;
parray[1]->i = 4;
std::cout << array1[0]->i << ' ' << array1[1]->i << '\n';
return 0;
}
The new output is:
1 2
4 3