Pointer to a object that scoping in the function - c++

I just think of a question about pointer,
the pointer p first initial in main function and point to object "a"
and then call function f , and change to point object "b".
but the scope of "b" is only in function. After call the function f, why the pointer p is still pointer to "a". Shouldn't p be NULL or something else?
void f(int*p){
int b = 10;
p = &b;
}
int main(){
int*p1 = NULL;
int a=6;
p1 = &a;
f(p1);
cout<<*p1<<endl;//output 6
cout<<a<<endl;//output 6
return 0;
}

C++ functions has value semantics , function f copies pointer p1, original p1 is not modified.
In f function, you tried to point pointer to local variable, this is dangerous.
If you intent to modify pointer p points to, you need to pass the address of pointer
void f(int*& p) // pass in reference to pointer
{
static int b = 10; // make it static,
// so p won't become dangling pointer when f returns
p = &b;
}

What happens:
Because you pass pointer by value, a local copy is created in function f, Then you assign another value (pointer to b) to that copy and leave the function. Original pointer remains unchanged.
Now let's suppose, that you modify the function in the following way:
void f(int * & p){
int b = 10;
p = &b;
}
Don't do this at home!
Now, the actual pointer is passed to function, no copy is created. Then a pointer to b is assigned to it and function returns.
Then you try to access the value pointed to by p1 - a value, which is no longer valid, because b no longer exists. You get an undefined behavior here: the best case scenario is that everything actually will work as you guess it would, the worst case scenario is that you'll get an Access Violation or worse - some data of your program may get corrupted (everything depending on platform and compiler).
Why C++ compiler doesn't notify you about that? Generally because C++ is not supposed to take care of you, such that you won't shoot yourself in the foot (actually, there are so many ways to shoot yourself in the foot using C++, that if you stack books containing these, you would reach Moon). C++ just does what you tell it to. You want to get pointer to b? Ok, no problem. You want to return a pointer from function? Why not, that's simply a 32-bit integer value.
The point is, that when writing in C++, you have to be very cautious not to write such code.
Edit: in response to comments
Imagine, that data is a building and pointer is a piece of paper with address of that building. When you pass pointer by value:
void f(int * p)
It is like you took another piece of paper and copied the address. If you then erase it and change to another one, the original address on the original piece of paper will remain unchanged.
Now if you do something like:
void f(int * p)
{
*p = 4;
}
It's like you actually went to the address written on the piece of paper and changed something in the building. If you then go to the address stored on the original piece of paper, the building will be changed.
Finally, if you do something like:
void f(int * & p)
{
}
It's like you passed the original piece of paper to the function, so if you change the address, it is changed also outside of the function.
Hope this helps you to understand how pointers work.

Here the pointer is passed by value i.e the function f makes a copy of it then uses it, and when it is done it destroys it. the initial pointer p1 is unchanged.

When your pointer becomes invalid, it doesn't magically take on a different or null value. It still points to the same place; it's just that that place is no longer valid.

Related

c++ - pointers and references : a simple example

I am working through a c++ book/guide, but the pointers and references seem a little vague to me. This is coming from myself as a C# programmer and c# mindset that uses
foo(ref int x) and bar(out int y)
A small piece of code I wrote to show the memory position and memory position value, but I do not fully understand what each means, and in what context this is in.
int main()
{
int i = 50;
foo(&i);
cout << "\n\n" ;
foo(i);
getchar();
return 0;
}
void foo(int& bar) // & refer
{
cout << "refer";
cout << "\n&bar = " << &bar;
cout << "\nbar = " << bar;
}
void foo(int* bar)// * pointer
{
cout << "prefer";
cout << "\n&bar = " << &bar;
cout << "\nbar = " << bar;
}
output shows:
pointer
&bar = 0018FC30
bar = 0018FD04
refer
&bar = 0018FD04
bar = 50
What does & and * in each case mean, and how does it affect the output?
ofcourse, I have added all necessary methods into the .h file
UPDATE AFTER READING SOME ANSWERS
int i (values from pointer, aka points directly to variable)
has a value = 50
has an memory address = 0018FD04
pointer which points to int i
has a value which is int i memory address = 0018FD04
has its own memory address = 0018FC30
thus, to clarify, using a "refer" or "&bar" in the example actually creates a new variable which duplicates the int i passed through in the foo(int& bar).
Instead of the new &bar value containing the 50, it will have the memory address of the int i.
TL;DR
foo(int bar) receives the "value" of the variable
foo(int* bar) receives the "value" of the variable, if changed, it will change the variable in the calling method.
foo(int& bar) receives the pointer/memory address of the variable.
I hope others find this as useful as I did, thank you all!
Okay, the pointer first :
void foo(int* bar)// * pointer
{
cout << "prefer";
cout << "\n&bar = " << &bar;
cout << "\nbar = " << bar;
}
You're calling it with
int i = 50;
foo(&i);
In this context, *bar will be 50 (get the value the int pointer is pointing to).
&bar is the address of the pointer that is created ( the pointer itself needs a place in memory too of course ).
bar is the address of the object the pointer is pointing to ( i in this case )
Reference case:
void foo(int& bar) // & refer
{
cout << "refer";
cout << "\n&bar = " << &bar;
cout << "\nbar = " << bar;
}
Here, bar will refer to i that you created in main. &bar will return the address of i and bar it's value, 50 in this case. References themselves don't have their own addresses.
Coming from C#, pointers can be thought of like classes, while values act more like structs - when you alter their members, you're either altering a copy (in the case of pass-by-value objects, which is not shown), altering the same object you've been passed (in the case of pass-by-pointer), or altering the same value including the reference to the actual value you've been passed (in the case of pass-by-reference). In other words, instead of the object's declaration controlling how it's passed, the implementation decides how it's passed.
For each method header, behavior is as follows:
void foo(int& bar) // & refer
When you pass using type& name, you're passing by reference, and you're passing the equivalent of C#'s ref (or out if you didn't give the variable a meaningful value to begin with). Even though you've passed a value, changes to the value, including changing the value itself, will be reflected in the calling scope.
void foo(int* bar)// * pointer
When you pass an object using type* name, you're passing the pointer to that object. You are, however, passing the pointer as a value, so while you could change members (moot in the case of an int) you could not change the value (bar) itself. Again like C#, this would be like passing a class object without the use of ref/out - reassignment won't be reflected in the calling scope.
Going over the use of & in code...
cout << "\n&bar = " << &bar;
In this case, & the "address-of" operator. Whenever you take &variable in code, you're going to get the memory address of that variable - printing this value will give your the hexadecimal address the variable lives in RAM, which is basically gibberish in all but the most technical debug and sample cases. This also applies to pointers - you can take the pointer of a pointer (of a pointer of a pointer... ad infinitum).
In C++ the default is pass by value. So if you have a f(X x) then the compiler is going to generate code that copies the class X every time you call the function. If X is large (like an array, string, map or something like that) you probably don't want a copy, for performance reasons. Making a copy also means that if you modify the parameter inside your function you only modify the copy so it won't be visible after you return.
Now to make things visible outside of the function you must modify the instance of the caller. To do this you must have a pointer(*) or a reference(&) to that instance. The immediately visible difference between the two is that you can compare the pointer to nullptr (it's more tricky for the reference), that for the pointer you must use -> to access it's members, vs . for the reference and that when calling you must take the address of the argument to get the pointer (f(&global_x)). In general you should use references where there argument can never be nullptr. You should prefer pointer when it's reasonable to call the function with that argument missing. These are equivalent with C# ref or out. There are more subtle differences between the two but they only become apparent if you are writing templates and libraries.
If you want to avoid the copy but you don't want to modify the argument you should use const, which asks the compiler to make sure that you don't accidentally modify the value. You can use it with both references and pointers.
Picking references vs. pointers is most of the time a ting of coding style. The most important thing is to be consistent because it is annoying having to lookup function definitions all the time to see if you used pointers or references that one time.
I am working through a c++ book/guide, but the pointers and references seem a little vague to me
You'll find plenty of explanations for this if you try searching, but here is my attempt.
A pointer is a variable that tells you where to find another variable, by pointing to it. A pointer is really just a number that corresponds to the address in memory of another variable. Examples of addresses are the 0018FC30 and 0018FD04 in your output.
A reference is an alias (another name for) a variable. If you have a variable a and you create a reference b to it, b becomes an alternative name for a.
The value of a reference is not an address like for a pointer, it's the value of whatever it refers to.
The interest of references is that when you copy them or pass them around, you're not copying the actual value (which can be expensive), you're only copying the name.
The main observable difference is that you can change what a pointer points to (by changing the value of a pointer, since its value is really just an address), but you can't change what a reference refers to (in a way, it becomes what it refers to).
What does & and * in each case mean, and how does it affect the output?
When you have a variable a, the expression &a means "take the address of a".
This is interesting, because if you have the address of a variable, you can make a pointer point to it.
And *a could be seen as more or less the inverse operation, if you have a pointer a, *a means "take the value at the address this pointer points to".
You can use &a on anything that has an address. You could even take the address of a pointer to create a pointer-to-pointer! But you can only use *a on something that behaves like a pointer, it would be meaningless otherwise.
Imagine we have:
int* a; // This holds memory addresses
a = new int;
cout << a; // This will print the memory address of your new int
cout << *a; // This will print the value at the memory address a is holding
cout << &a; // This will print the memory address of the pointer variable.
If you declare a function that takes a pointer as a parameter, you should pass a pointer and not a static variable.
I hope this helped you even if its just a little bit.

function declaration or prototype. How do i define it?

I have been working on linked lists and trees recently. But i am not sure when to declare a function as:
preorder(struct node* root);
or
preorder(struct node** root);
when both work quite the same. To be more precise when do i have to design my function as double pointer and as a single pointer.
Thanks.
P.S: insertion of a node in linked list needs to have double pointer as in:
insert(struct node** root,int value);
unless the root node is defined as a global value. While the preorder works well with a single pointer. If anyone can explain with this as an example it would be highly helpful.
That depends on what preorder() does. If it prints some stuff without modifying the list/tree, you only need a single pointer. If there is a chance that the root will have to be replaced, you need a double pointer.
This is because arguments are passed by value in C. You cannot modify the original variable if a copy of it is passed to your function:
int inc(int x)
{
x = x + 1; // this will never work
}
To get around this, instead of passing in the argument you can pass in the address of that argument (a pointer to it). The function can then dereference the pointer and modify the value it points to.
// usage: inc(&x) where x is an int
int inc(int *ptr)
{
*ptr = *ptr + 1; // this will work
}
With your list/tree, you are already using pointers. This lets you access and modify the pointed-to object (e.g. get/set the next member of the root), but doesn't let you modify the pointer itself (e.g. replace the root with a different node). To do that, another level needs to be introduced, hence the pointer-to-pointer-to-node.
preorder(struct node** root);
Here you pass the address of root, because you may wish to update it withing the function.
preorder(struct node* root);
Here you simply use root to transverse the data structure, without modifying the root.
It's kind of confusing, but I will give it a shot and maybe my way of explaining will make sense to someone :)
Every variable in a function's scope is defined in a standard way, essentially.. (variable type) (variable name). Whether that's:
int foo; // an int called foo
or
char *bar; // a char * called bar
or
struct xyz *blah; // a struct xyz * called blah
and the way you treat foo, bar, and blah are the same when you pass them as arguments to another function. If you want the called function to just look at or use the variables, you can pass them as they are (by value) which creates a copy of the values (an int, or the address of a char, or the address of a struct xyz). So, if you change the value of the int, or the address of the struct xyz in the called function, it is only changed for that local copy of the original variable.
If you want the called function to actually change the value of the original variable (increment foo, malloc memory for bar, or change which element in a list blah points to for example) you need to tell the called function WHERE to make that change (pass them by reference) which results in the called function being declared as f(int *foo) or f(char **bar) or f(struct xyz **blah).
People get caught up on levels of indirection but all that really matters when you're calling another function is what your intentions are with respect to using or changing the variables in the local scope.
You pass a pointer instead when you want to change the thing being passed to the routine. Your confusion arises because the thing is also a pointer.
So if you want to pass a pointer to a routine, and you also want to (potentially) modify the pointer itself, use a double pointer.
If you want to pass a pointer to a routine but all you want to do is change or query what the pointer is pointing to use a single pointer.
That's the difference, do you want to change the pointer or do you want to access what the pointer is pointing to.
Since question is tagged both C and C++, here is a look at the difference from that perspective. This answer does not touch C++ container classes or smart pointers, which should usually be preferred in C++ code. Below are 4 cases, two which can modify caller's struct and caller's pointer, and two which can only modify contents of given struct.
C++ modify pointer
When you want the function to modify a pointer, and have the pointer values returned to the caller in C++, you would do this using a reference to pointer:
void clearNode(struct node *&n){
n->field = 0; // modify caller's struct
n = nullptr; // set caller's pointer to NULL (C++11)
}
...
struct node n; // value
struct node *np = &n; // pointer to node
clearNode(np); // OK, np becomes null, n.field becomes 0
clearNode(&np); // will not compile, &np is not right type
clearNode(&n); // will not compile, &n is not lvalue
C modify pointer
In C, same code would be like this (also works in C++, though above version would be better and cleaner):
void clearNode(struct node **n){
(*n)->field = 0; // modify caller's struct
*n = NULL; // set caller's pointer to NULL
}
...
struct node n; // value
struct node *np = &n; // pointer to node
clearNode(np); // will not compile, np is not right type
clearNode(&np); // OK, np becomes NULL, n.field becomes 0
clearNode(&n); // will not compile, &n is not of right type
C modify only struct
But if we write same code with just pointer, it will work just a bit differently:
void clearNode(struct node *n){
n->field = 0; // modify caller's struct
n = NULL; // change local parameter, which in this case has no effect anywhere
}
...
struct node n; // value
struct node *np = &n; // pointer to node
clearNode(np); // OK, except np is not modified, n.field becomes NULL
clearNode(&np); // will not compile, &np is not of right type
clearNode(&n); // OK, n.field becomes NULL
C++ modify only struct
And finally, same code in C++ would be cleaner this way:
void clearNode(struct node &n){
n.field = 0; // modify caller's struct
// no pointer, nothing to set to NULL
}
...
struct node n; // value
struct node *np = &n; // pointer to node
clearNode(np); // will not compile, np is not of right type
clearNode(&np); // will not compile, &np is not of right type
clearNode(&n); // will not compile, &n is not of right type
// these work, n.field becomes 0:
clearnode(n);
clearnode(*np);
Your question
So, the thing to take from above is, if you need to modify callers pointer, pass pointer to pointer (C and C++) or refrence to pointer (C++). This comes at a cost: you must always pass a modifiable pointer variable, and double indirection also has small overhead. Syntax for both is shown above.
If you do not need to modify callers pointer, but need to modify the struct contents, pass a pointer (C and C++) or reference (C++) to struct. Syntax for both is shown above.
Third case, when you don't need to modify anything, is not covered above, but has 3 basic alternatives: pass by value (C and C++, clean syntax but copies entire struct), pass by pointer to const (C and C++, a bit uglier syntax but passes just address) or pass by const reference (C++ only, clean syntax and passes only address).
To summarize, use double pointer (or reference to pointer) when you need to modify caller's pointer. Otherwise, pass a pointer (or a reference), or even a value if struct is small.

C++ function parameter takes an address of a pointer as an argument. How is this used? What is it for?

Imagine a function like this:
function(Human *&human){
// Implementation
}
Can you explain what exactly a *& is? And what would it be used for? How is different than just passing a pointer or a reference? Can you give a small and explanatory sample?
Thank you.
It is like a double pointer. You're passing the pointer by reference allowing the 'function' function to modify the value of the pointer.
For example 'human' could be pointing to Jeff and function could modify it to point to Ann.
Human ann("Ann");
void function(Human *& human)
{
human = &ann;
}
int main()
{
Human jeff("Jeff");
Human* p = &jeff;
function(p); // p now points to ann
return 0;
}
void doSomething(int &*hi);
will not work. You cannot point to references. However, this:
void doSomething(int *&hi); // is valid.
It is a reference to a pointer. This is useful because you can now get this pointer passed into the function to point to other "Human" types.
If you look at this code, it points "hi" to "someVar". But, for the original pointer passed to this function, nothing will have changed, since the pointer itself is being passed by value.
void doSomething(int *hi)
{
hi = &someVar;
}
So you do this,
void doSomething(int *&hi)
{
hi = &someVar;
}
So that the original pointer passed into the function is changed too.
If you understand "pointers to pointers", then just imagine that, except when something is a reference it can be treated like a "non-pointer".
"Takes an address of a pointer" - No, it doesn't. It takes supposed to take a reference to a pointer.
However, this is a syntax error. What you probably meant is
rettype function(Human *&human)
(Yes, it's also missing a return type...)
Since you wrote this code off the top of your head, I'm going to assume you meant to do something like this:
void f(T *&) {}
This function signature allows the pointer passed to become modifiable, something that isn't allowed with the alternate syntax int *. The pointer is effectively passed by reference as others here call it.
With this syntax, you are now able to modify the actual pointer and not just that which it points to. For example:
void f(int *& ptr) {
ptr = new int;
}
int main() {
int * x;
f(ptr); // we are changing the pointer here
delete x;
}
Summary (assume types are in parameters):
T *: We are only able to change the value of the object to which the pointer points. Changing the parameter will not change the pointer passed.
T *&: We can now change the actual pointer T, and the value of the object to which it points *T.
Even though it looks just like the address-of operator, it's not - it's a reference parameter. You use a reference when you want to be able to change the value at the caller's end. In this case the pointer is probably being set or changed within the function.

Why swapping two values based on pointers don't work outside function scope?

I haven't programmed in C++ for a number of years, so I decided to refresh my memories on pointers.
In the classic example of swapping between two numbers, the example is
void swapPointersClassic(double *num1, double *num2)
{
double temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
This allows us to make function call like swapPointersClassic(&foo, &bar); and because we pass in the memory addresses of both variables foo and bar, the function will retrieve the values and do the swap. But I started to wonder, why can't I do the following?
void swapPointers(double *num1, double *num2)
{
double *temp;
temp = num1;
num1 = num2;
num2 = temp;
}
That seems to make more sense to me, because we only have to create enough temporary storage for storing the memory address num1 (instead of a full temporary storage for storing a double value *num1). However, it seems that function scope limits the effect of pointer swapping. After making the call swapPointers(&foo, &bar);, I can see that within the function swapPointers, foo & bar are indeed swapped. Once we exit the swapPointers function, foo and bar are no longer swapped. Can anyone help me understand why this is the case? This behavior reminds me of the typical pass by value approach, but we are passing by pointers here. So that means we can only touch the values pointed by those pointers, but not the pointers themselves?
In fact you don't really pass by pointer. You pass two pointers by value. Passing pointers in itself is not enough - you have to dereference them. The act of dereferencing the (copies of the) pointers makes the magic happen and it is the actual place where scope traversal is achieved.
Modifying the arguments of a function is local to the function, even if the arguments themselves are pointers. You must dereference them in order to access the memory pointed to by them (again, "passing by pointer" is more than passing pointers - it's passing pointers and using them properly).
Also, consider the following. If your second approach worked, and the two pointers were swapped then it would mean that the addresses of the variables are exchanged. This doesn't quite make sense.
By the way, in C++ we have a true pass-by-reference calling convention, so there's
no need to mess with pointers:
void swap(double &a, double &b)
{
double temp = a;
a = b;
b = temp;
}
float a = 1, b = 2;
swap(a, b);
(It's just a matter of implementation that the compiler will most likely realise this behavior by actually using pointers, but at least you don't have the headache.)
If you want to swap pointers, not their values, you need to pass pointer of pointer:
void swapPointers(double** num1, double** num2)
{
double* temp = *num1;
*num1 = *num2;
*num2 = temp;
}
You can see an example in: http://ideone.com/iklCta
You can work even with references:
void swapPointers(double*& num1, double*& num2) {
double* temp = num1;
num1 = num2;
num2 = temp;
}
Example: http://ideone.com/w4k9mV
This is useful when you work with huge objects (e.g.: image data) and you do not want to move a lot of memory, but only references.
This is a good question but once you have it figured out please use std::swap or std::iter_swap instead of writing your own.
If foo and bar are pointers, calling std::swap(foo, bar) would exchange the addresses between the two pointers. Calling std::swap(*foo, *bar) or std::iter_swap(foo, bar) would dereference the pointers and exchange the objects the pointers point to.
You are passing the pointers themselves by value; num1 and num2 are local copies of pointers that the caller calls the function with. So the swapping is not visible at the callsite when the function exits since the modifications were only made to variables that are local to the function.
Instead, change the function to take references to the pointers and your swapping code will work as intended to.
void swapPointers(double*& num1, double*& num2) { ... }
Now, your function parameters are aliases for the pointers that the caller passes to the function, and whatever you do to them will affect the pointers in the caller's context as well.
When you call
swapPointersClassic(&foo, &bar)
You are taking the address of two items on the stack. These values are being passed in as temporaries and are copied by value. In your function body, you swap where these temporaries point, but don't move where foo and bar are pointing.
Most importantly, foo and bar live on the stack. You can't change where variables live in the stack in C++. A value is mapped to a spot on the stack and lives there. You can get a pointer to where that value lives to do pass-by-pointer (similar to pass-by-reference) but just by changing where that temporary pointer points you aren't changing where the pointed-to object lives.
When you pass double *num1 into a function, you're passing in a pointer by value. That creates a variable in the function scope that holds the address of a double. When you assign to that, you're changing the value of the pointer in the function scope.
Just like you have to pass in a pointer to a double, dereference it, and assign to swap a double, you have to pass in a pointer to a pointer, dereference it, and assign to swap a pointer.
Pointers 101: a pointer is a piece of paper with the address of a house on it.
By writing &bar, you are taking the house called bar and writing its address down on an anonymous piece of scrap paper.
You then call a function with that pointer as an argument. What happens here is that the function makes another copy of the piece of paper.
Your swap function then takes two such local copies and swaps what address is written on them.
So that does nothing outside the function. Clear?
Now fundamentally even if there was not a copy inside the function of the address all you are working with is scrap paper with house addresses on them. No changes to such paper can actually move the data stored in house bar or foo.
As proper answer(s) to this question had already been posted, I would just make some things clear.
Swapping values of two variable using references is bad practice in general and should be avoided. the reason is references are not supposed to be re-assigned. Look at the following code :
1. void swap(double &a, double &b)
2. {
3. double temp = a;
4. a = b; //Not what you think
5. b = temp;
6. }
7.
8. float a = 1, b = 2;
9. swap(a, b);
on lines 4 and 5, you are clearly violating the common rule - 'Never Re-assign references'.
If you really need to change value of the variable(s) always prefer 'pass by pointers' rather than 'pass by reference'.
The following code makes sense and a good practice IMO.
1. void swapPointersClassic(double *num1, double *num2)
2. {
3. double temp;
4. temp = *num1;
5. *num1 = *num2;
6. *num2 = temp;
7. }
8.
9. float a = 1, b = 2;
10. swap(&a, &b);
Agreed that references are cleaner and easier to use, and they do a better job of hiding information, as you saw in the first example.
References cannot be reassigned, however. If you need to point first to one object and then to another, you must use a pointer.
Rule of Thumb:
DON'T use pointers if references will work.
DON'T try to reassign a reference to a different variable. You can’t.

Use an un-initialized pointer as a function parameter

As I want to pass an uninitialized pointer to a function, it goes runtime error.
but if I pass this pointer as a reference, it works OK. I cannot explain why...
class Body
{
};
void check(Body* b)
{
b = new Body();
}
void checkRef(Body* &b)
{
b = new Body();
}
int main001()
{
Body* b;
//check(b);// error: The variable 'b' is being used without being initialized. (in VS2010)
checkRef(b); // OK
return 0;
}
Whats the difference when b is passed to check and checkRef? I get the runtime error in VisualStudio2010. error:The variable 'b' is being used without being initialized.
EDIT: it was a VS2010 debug output. the "error" doesn't appear in release version
In order to be equivalent to the checkRef version, your check function should read:
void check(Body** b)
{
*b = new Body();
}
and called as
check(&b);
If you don't pass the address, as you do in check(b), then you are passing the current value of the pointer b which is indeed uninitialised.
Body* b does not set b to point to anything sensible. So it may point to some random location which could cause the earth to shift a bit.
Passing it to check(by value for the pointer) does not make it initialised in any way
void check(Body* b)
{
b = new Body();
}
If you passed it by pointer to pointer, it should be okay
void check(Body** b)
{
*b = new Body();
}
And the call
check(&b);
Better done in C++ way with the reference example you give since that updates the referenced pointer value to point to the newly allocated Body
In Body * &b b is an alias of/reference to the b in main - so when you assign to it you modify the b in main. In Body* b b is a local copy of the b in main, you're modifying this local copy and not the b in main.
Your runtime error is likely due to using the uninitialized b in main.
EDIT: The actual error you get is an extra check-for-typical-problems mechanism embedded into your code by your compiler. It detects that you pass something uninitialized by value, which doesn't make sense, and therefore generates this error.
If you disable this behavior, the application will appear to function properly until you try to dereference the uninitialized b in main
I don't know why you're seeing a run-time error; at most I would expect to receive a compile-time warning/error. But you can probably fix it by initialising b to NULL (but this won't fix your program; see below...)
The difference between the first and the second function call is that the first one will cause a memory-leak. You are passing the pointer by-value, so inside check() you are working with a copy of that pointer. You assign this copy, but this doesn't affect the value of the pointer in main(), so when you leave the function, there is no way to access the memory that was obtained by new.