I want to check if an int pointer parameter is nullptr and if so, I want to create an int array, fill it with data and the finish the function.
It works up until I leave the scope of func(intPtr) then the intPtr address is set to 00000000. How do I get the new int array to exist out in the main function?
You have to pass a pointer to a pointer to function func() to allocate the array inside funcion func(). Because this is brainfuck, consider using std::vector.
1 2 3 4 5 6 7 8
std::vector<int> func() {
return std::vector<int>(6);
}
int main() {
std::vector<int> v = func();
std::cout << v[0] << "\n";
}
You are sending a COPY of intPtr to the function. The COPY then gets updated to point at the new array, and then the COPY is destroyed at the end of the function. The original intPtr is untouched.
Don't send a COPY; pass by reference so the function works on the original intPtr:
Now, that done, here are some other notes to just be aware of; in modern C++, as a very strong rule, don't use arrays, don't do manual memory management (i.e. don't use new or malloc).
How do I get the new int array to exist out in the main function?
The new array you created exists forever (or at least until the program ends). This is a memory leak; you've created an array using new, and then your (original) code loses the pointer to it. The memory is still allocated. The array still exists. You just lost the pointer to it.
To be fair another option is to have the function return an int pointer, i.e., int* func(). Doing this there is no need for any parameters. In "main" the line would be intPtr = bar.func();.
To avoid rewriting the program passing the pointer by reference is the best and quickest option.
You are now sending a COPY of mustBePtr to the function FuncInMain. The COPY then gets passed to func (not another copy; you're passing by reference to func so func does not receive a copy), and then the COPY is updated in func, and then the COPY is destroyed at the end of FuncInMain.
This is basically the exact same problem.
1 2 3 4
int FuncInMain(int* intPtr) // Receives a COPY of the int-pointer
{
// SOME CODE
}
1 2 3 4
int FuncInMain(int*& intPtr) // Receives the actual int-pointer
{
// SOME CODE
}
See the difference? We already showed you this once.
Ok, so if I understand it correctly, the problem is that FuncInMain() must take an int pointer as argument (which is a requirement for the task), but then there is no way of getting the original address of mustBePtr. Is that correct?
The possible caes I m looking at is if mustBePtr is a nullptr it should be populated (is that the right word?) with an int array.
#include <iostream>
usingnamespace std;
// This won't change the value in the caller
void foo ( int a ) {
cout << "foo::a=" << a << endl;
a = 2;
cout << "foo::a(new)=" << a << endl;
}
// This will change the value in the caller
void bar ( int &a ) {
cout << "bar::a=" << a << endl;
a = 2;
cout << "bar::a(new)=" << a << endl;
}
int main ( ) {
int v = 42;
cout << "main=" << v << endl;
foo(v);
cout << "main after foo=" << v << endl;
bar(v);
cout << "main after bar=" << v << endl;
}
Just to beat the dead horse...
pointers are nothing special. if you pass one to a function by value, when that function ends and you pop back to where you were, its unchanged.
so
void foo(int x)
{
x = 3;
}
int y = 11;
foo(y);
//what is y here? its 11.
if you put an & on it in foo (int &x), then y is 3 instead.
pointers work the same way.
void foo(int *ip) //pass by value
void foo(int *&ip)//pass by reference. this is what you want. yes, its weird looking. you MUST understand that the TYPE is {int*} and its a reference to one of those. Its CRITICAL to understand this.
and beyond that, its ALSO CRITICAL to know that you can change what is pointed to off a value passed pointer.
that is:
void foo(int *ip) //passed by value
{
ip[0] = 1234; //this change will remain after the function ends. The pointer was passed by value. the memory where it points is a free for all area and change it anywhere it stays changed.
}
I am to write the following function for finding a path:
int FromStartToGoal(const Vector2 mapSize, const Vector2 start, const Vector2 goal, const unsigned char* grid, int* mustBePtrBuf, const int buffersize).
The function returns the amount of steps to reach the goal, grid is a char array mustBePtrBuf is an array with all indices you passed and buffesize is the max amount of steps allowed in mustBePtrBuf.
Everything is wet up and works perfectly, I just had a thought "what if the user sends in a nullptr? Should I create a new array for them?".
> I just had a thought "what if the user sends in a nullptr? Should I create a new array for them?".
Or just return an error value telling them that it can't be nullptr.
The problem with allocating things for someone unexpectedly is that you then push the burden of freeing that memory onto the caller. Maybe they don't want that (or expect it), and you end up with memory leaks.
This is why std::vector exist, to not think about memory leaks. Your function calculate the indices from start to goal. This it the result. Return is from the function.
I just had a thought "what if the user sends in a nullptr?
what is the requirement and design here is the question. Don't go rogue and fix things your own way without consulting the requirements and designs. Perhaps you should stop the program here (fatal, unexpected null and no way to resolve the issue). Maybe you should do nothing, and warn the user. Maybe you should create it for them. Maybe something else is needed. There is no way to tell you what to do here, because we don't know what is needed for your code.
if you need to create it for them, they need to delete it, or you can wrap your pointers in a dumb pointer class (self destruct when going out of scope) or use one of the advanced C++ pointers (I don't know which is best here; I have not spent time on new pointer types yet, since I know how to use the old ones).
Try to avoid dynamic memory. Use the tools that do it for you if you can. If you must use it, be sure you design carefully who owns what memory (responsible for delete) or use some self-cleaning strategy.
Thank you everyone for all your help. It has been a great help, I have learned lots of things apart fomr how to handle pointers ad references. I will keep memory leaks in mind in particular.