I have a simple c++ question concerning passing an array to a function foo(). Assume I have two arrays A and B:
double* A=new double[3];
and
double B[3];
When I pass both to the function
foo(double* A; double *B)
which is intended to manipulates both arrays. However by executing
foo(A,B)
foo is acting on a copy of A and only the changes to B remain when leaving foo().
This is not the case if foo is defined as
foo(double* &A; double *B).
My question: Why is a copy of a created although I pass the address of A like double* A (as in the case of B) in the first example of foo()?
foo is acting on a copy of A and only the changes to B remain when leaving foo().
What exactly are you doing inside of foo? Changes to the objects themself should be visible outside of foo in both cases. If you are trying to change the value of pointer A, it won't be visible outside of foo - a copy of the pointer is passed to the function, but of course it still points to the same array.
If you want to pass an array reference to a function you have to use a double pointer reference:
foo(double** A, double **B);
double** A=new complex<double>[3];
Related
I have the following code:
class B{
/*
...
*/
};
class A{
B** elements;
public:
A operator+=(const B& b){
// this->elements[0] = &b;
}
A(int number){
this->elements = new B*[number];
}
/*
...
*/
};
int main(){
A a(10);
return 0;
}
What I want is that the += operator should add the B object(operator's right side) to the A object's elements member.
So let's say I modify main to :
int main{
A a(10);
B b();
a += b;
}
After this a.elements[0] should be the b object.
I commented a line which is not working,but shows what I want.Uncommenting it gives the following error: invalid conversion from const B* to B*
The real code is much longer of course, it's enough if you show me how to make the += operator always assign the B object to A.elements[0], then I can edit my code as neccessary.
Thanks
Focusing your issue, a B* is not a B const*: on the first you are allowed to call methods which are not const, while this is not true for the latter.
And the compiler is complaining about this: you declare an array of pointers to modifiable Bs but then you try to store a pointer to an unmodifiable B inside it. So if you merely want to fix this problem you can decide for example to store unmodifiable Bs:
B const** elements;
public:
A& operator+=(const B& b) {
this->elements[0] = &b;
return *this;
}
A(int number) {
this->elements = new B const*[number];
}
But there are serious issues in your code:
you are taking the address of a const B& but where is this B coming from? It could have automatic storage and become an invalid pointer somewhere in the future
there is no way to know who is owning the pointer to B objects so who is responsible of releasing it.
It's C++, you have std::unique_ptr, std::shared_ptr, std::vector, just trying to do things as you would do them in C without even attempting to make them safe and secure doesn't make any sense.
You have some serious issues with your design.
A operator+=(const B& b){
// this->elements[0] = &b;
The idea here is to insert b into your collection, but your collection is little more than a pointer to some (unknown length) amount of raw memory. You do not have a way to know if elements[x] exists in order to store &b. For that matter, you don't know if elements exists at all. You will need more bookkeeping to store lengths.
But worse, you pass a reference to a const B and take its address, storing that pointer in your collection. What if the argument is a reference bound to a temporary? (Rvalues can bind to const lvalue references). In that case, the moment you've finished inserting the pointer into your collection the object it points to is destroyed.
That is assuming you work around your const-incorrectness, as you take a reference to a const b, take its address, and hope that it points to a non-const B. It doesn't. Casting it away can result in undefined behavior if b really points to an actually const object (and the non-const interface of b is used through your pointer.)
Your grow function leaks memory and loses the old elements. Yes, it's pseudocode but too far from anything real to base ideas on.
There is a lot of really dangerous ideas in just a few lines. Here are suggestions:
do not store raw pointers
even more strongly, do not store pointers obtained from reference arguments
make lifetime management easy; use smart pointers to show who owns the memory of passed-in objects
maintain const correctness. If you take (smart) pointers to const objects, store them as (smart) pointers to const objects.
when you resize allocations allocations, worry about what happens to the old objects and memory. Containers help reduce this effort.
use container classes instead of managing raw memory yourself and many of your problems vanish (but not the lifetime management issue of the arguments.)
I want to pass a pointer to a function.
Lets say I am creating a structure and declare a pointer to that structure. I allocate memory to that pointer and then I want to "pass" that pointer to a function so I can do stuff to that block of memory. How I do that?
It is done the same way as passing a normal variable. You shouldn't think of a pointer any different than a variable, as a pointer is a variable (although a bit special).
Say you have an integer and a pointer to that integer:
int a = 0;
int * ptr = &a;
Note that ptr and a are both variables, and in this instance, we use the reference operator & to reference a by &a which gives the address of a -- this is a pointer to a.
Now say you have two functions:
void foo(int i){}
void bar(int * p){}
Now these two functions do the same thing (nothing), but one takes an int and one takes a pointer to an int, int *. If you called foo(a) and modified i, i would be modified in the function body, but have no effect on a. If you called bar(ptr) and modified the value pointed to by ptr by using the dereference operator * as something like *ptr = 1, it would modify the value pointed to by ptr, which in this case would be a.
In your case, passing a struct would be just the same. Say you have a structure
struct MyStruct { int b; };
And had two more functions
void structFoo(struct MyStruct m) {}
void structBar(struct MyStruct * mp) {}
You could work on the pointer in the same way as our above int and int * functions, although you would now also have to access the struct components by dereferencing the struct with (*mp).b, or the shorthand version mp->b.
For ease of use, you may also want to do something like
typedef struct MyStruct MyStruct;
Which will allow you to use MyStruct as the type name rather than requiring struct MyStruct as in the above functions, although you may want to avoid doing this until you fully understand what is happening and get through difficulties with pointers.
Hopefully that gives you some idea of what is going on, although the C++ tutorial on pointers gives a much more in-depth discussion than what I can provide.
It would be a good exercise to create some small programs and mess around with pointer and regular types while printing the results to help understand what is happening where. You should remember that to allocate a pointer, you're going to need to use either new or malloc(), otherwise you will have a SEGFAULT error. This is not an issue when referencing a variable declared as I have done with &a above as the memory is already allocated when a declaration such as int a is made. A declaration of a pointer allocates the memory for that pointer, but not the memory that it points to. This eventually leads into the difference between the stack and the heap, although I wouldn't think about that until you have a very thorough understanding of pointers.
Structure in c/cpp is like all the other types. You can use & and * as you do it for int.
If we have the following code, the memory for variable b is not taken, when we call function f. But if the function f would have the prototype void f(int* &a) then the memory would be allocated. How is this possible?
#include <iostream>
using namespace std;
void f(int* a)
{
a = new int[10];
a[0] = 55;
}
int main()
{
int *b;
f(b);
return 0;
}
EDIT:
Well I got the main idea but why is still possible then?
void f(int a[])
{
a[0] = 5;
}
int b[] = {1,2,3,4,5};
f(b);
//The value of b[0] will be 5 after the end of function call
You are passing the pointer by value, so f has its own copy of it. The pointer a is local to f, so the caller has no access to it (and the memory allocated is leaked, BTW).
When you pass the pointer by reference, a is semantically the same pointer as was passed. So the pointer passed by the caller points to the memory allocated in the function.
Pointer int * b; is actually a variable. A variable which hold an memory address of an integer. For example:
int n;
int* b = &n; // pointer b is pointing to n
Since a pointer is a variable you can pass it by value or by reference. Here you pass it by value to the function. Check also the http://en.cppreference.com/w/cpp/language/pointer.
In the case of void f(int* &a) you pass by reference the int* a variable. It is a variable (that hold a memory address of a variable of type int) which it is not initialized to any value yet in your code (in main()).
In your second code. In the function void f(int a[]) when you pass int b[] = {1,2,3,4,5}; with f(b); you make "implicit" conversion of array name to a pointer. The problem is that the function f() does not know the size of the array. For example you use this calls in functions like strlen() where you pass null terminating strings. Check book "The C++ Programming Language", 3rd Edition by Bjarne Stroupstrup page 92.
There is also a basic rule: a[i] <=> (*(a+i)). So your function void f(int a[]) is equal with void f(int* a) definition. Check "Navigating C++ and Object-oriented Design" by Gail Anderson, page 40: http://books.google.gr/books?id=b-NiT6w8FTAC&pg=PA40#v=onepage&q&f=false
I have class A, then I made a vector of class A;
std::vector<A> b, and i initialize it correctly.
I have one member function of another class, which has a member pointer which point to a
vector of A;
In this class, I also have a member function, and inside this member function.
I fist build a reference to the vector of class A, and initialize it use the deference of the pointer, The reason is the member reference can only assign value once, so I use pointer, but inside the member function, the syntax of reference is more clean.
the question is, in the member function, if i delete the reference to that vector, does it only delete the reference or delete the whole container the pointer point to. The container contain object not pointer.
Thanks
When the reference goes out of scope it's not going to destroy the original object.
I assume this is the situation:
class A {};
class B
{
std::vector<A>* pA;
public:
B( std::vector<A>* p ): pA(p) {}
void foo()
{
std::vector<A>& arr = *pA;
//do stuff with arr
// Arr and pA are still valid after the end of this function
}
};
int main()
{
std::vector<A> Arr;
Arr.push_back( A() );
B b( &Arr );
b.foo();
}
You should provide an example but with what you provided, it's already a big no no!
If you store a std::vector<A> you're storing actual objects of type A. When your vector grows, the items will be copied to a new memory location, therefore keeping pointers or references to items inside a vector of objects won't work as you expect.
Consider storing pointers instead (std::vector<A*>)
Deleting your pointer to a std::vector<A> should delete everything. If you switch to std::vector<A*> you should delete every object in the vector then delete the vector.
I've tried to allocate a memory this way:
main:
X** a;
func(a);
func:
func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
a = &array;
}
If using the debugger I see that when I am in the function func everything is okay = i can write to the array and a really points to the array but the moment I am back to the main I something changes and I can't access the array through a (on the debugger it writes something like: Target request failed: Cannot access memory at address 0x909090c3 and so on).
Where is my mistake?
Note: It does compile but has a run-time problem if trying to access (print for example) the array in the main section.
Thanks.
You have to change your main like this:
X* a; // create an uninitialized pointer
func(&a); // pass the address of that pointer to the function
And inside your function, do this:
void func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
*a = array; // change the value of the pointer to point to the array
// you allocated
}
Note that in C++ the way to go would be to use an std::vector<X>:
std::vector<X> func() {
std::vector<X> buffer(5);
// do stuff with buffer
return buffer;
}
std::vector<X> foo = func();
This would create a new vector inside the function and return a copy of that vector to the caller. Note that the copy would be optimized away.
You are changing the local copy of your variable a, it will not propagate to the outside of function (ie. the calling scope). Easiest solution to your problem is to pass a by reference, but you can also pass it using a pointer and dereferencing the pointer inside of your function.
See the below examples.
Using a reference
void func (X*& a) {
X* array = (X*) malloc (5*sizeof(X));
a = array;
}
...
X* a;
func (a);
The ampersand on the line below states that a is being passed by reference, ie. changing it inside the function will make the change propagate to parameter the caller used.
void func (X*& a) {
Using a pointer-to-pointer
This can be hard to comprehend if you are inexperienced when it comes to pointers, but we will make func take a pointer-to-pointer as it's parameter and pass in the address of variable a from main.
Upon dereferencing the pointer-to-pointer we can safely store away the information we want.
void func (X** pointer_to_a) {
X* array = (X*) malloc (5*sizeof(X));
*pointer_to_a = array;
}
...
X * a;
func (&a); // pass in address of a
NOTE
Since you are writing C++ (stated by question title and tag) you should not be using std::malloc, instead refer to operator new.
You're setting the local pointer a to the address of the local pointer array, when you want to set the target of a to the value of array:
*a = array;
and call it as
X * a;
func(&a);
It would be less confusing to return the pointer (i.e. X * func()).
Also, you've tagged this C++ not C, so you shouldn't be using malloc; use the standard containers, or if they don't work for you, allocate using new and manage the memory with a smart pointer.
In main, a is a pointer to a pointer. That means that two things have to exist: the block of memory, and a pointer pointing to it. Then a can point to that pointer. In your attempt, that middle pointer is being allocated on the stack of func, and when func returns, it's destroyed, so that's not going to work.
You could do this:
X* pa;
X** a = &pa;
func(a);
func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
*a = array;
}
Think it over:
a = &array;
array is a local variable allocated on heap, &array will be junk when its scope is over (the function body).