2

I would like to understand the difference between passing *&p and *p and when to use one over another.

Say, I have a init function like the following.

void init(lua_State *L) {
    L = luaL_newstate(); //allocate new memory to L
}

And in main() if I try to access to L, it crashes.

lua_State *L;
init(L);
do_something(L);//crash

However, when I change the argument type to lua_State *&L, it no longer crashes.

Is it because allocating new memory changes value of pointer?

If so, isn't it better and safe to always pass with *& instead of *?

Is there any general rule about this?

Zack Lee
  • 2,784
  • 6
  • 35
  • 77
  • Possible duplicate of [Difference between pointer-to-pointer vs reference-to-pointer (C++)](https://stackoverflow.com/questions/8424132/difference-between-pointer-to-pointer-vs-reference-to-pointer-c) –  Jun 27 '18 at 04:04
  • 1
    Possible duplicate of [c++ passing by const pointer or reference to const pointer](https://stackoverflow.com/questions/49788157/c-passing-by-const-pointer-or-reference-to-const-pointer) – Joseph D. Jun 27 '18 at 04:04
  • You are passing `L` in this example. Do you actually mean to ask about the difference in *parameter type* `T *p` versus `T *&p` ? – M.M Jun 27 '18 at 04:37
  • @juanchopanza [yes, it would](https://ideone.com/UP215y) – Remy Lebeau Jun 27 '18 at 05:20
  • 1
    @RemyLebeau I let myself get confused by the confusing title, which I have now fixed. – juanchopanza Jun 27 '18 at 06:13

2 Answers2

4

I would like to understand the difference between passing *&p and *p and when to use one over another.

Your objective is to change the value of L in init and make sure that the change is visible in the calling function.

Passing a pointer to init does not work because any changes to the argument is only a local change. It does not change the value of the variable in the calling function. Hence, the pointer remains uninitialized in main. Using the uninitialized pointer in main leads to undefined behavior, which manifests as a crash on your system.

I suggest changing the argument type of init to a reference to a pointer. When you do that, any changes to the argument will be visible in the calling function.

void init(lua_State*& L) {
    L = luaL_newstate(); //allocate new memory to L
    // The new value of L will be visible in the calling function.
}

and use it as

lua_State *L;
init(L);
do_something(L);

Suggestion for better coding practice - always initialize your automatic variables at the point of declaration.

lua_State* L = nullptr;
init(L);
do_something(L);
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • @ZackLee To avoid such crashing, you can always do this: `if(L) do_something(L);`. by which you can check whether pointer holds anything/ initialized. – JeJo Jun 27 '18 at 05:03
  • @JeJo that will only work if the pointer is initialized. In the OP's code, it wasn't, so the behavior of such an `if` would be undefined – Remy Lebeau Jun 27 '18 at 05:22
  • @RemyLebeau Yes true. I had initialised `lua_State* L = nullptr;` before checking. Forgot to mention it. Thanks. – JeJo Jun 27 '18 at 05:25
-1

Consider a variable int p, then &p means the address of p, finally *&p = p, the value of p

Now consider a variable int *p, then p points to the address of p, and *p is the value of the variable

I. Ahmed
  • 2,438
  • 1
  • 12
  • 29