Pointer-to-Pointer and Reference-to-Pointer

Introduction
Why We Need Them
Syntax of Pointer-to-Pointer
Syntax of Reference-to-Pointer
Syntax of tracking reference to a handle(C++/CLI)(new)
Preference of One Over the Other
Do Not Mistake Every Pointer-to-Pointer Argument
Reference to Pointer Type (RTTI)
What Are Other Alternatives?
Conclusion
History

Introduction

This article explains the reason behind using pointer-to-pointer and reference-to-pointer to modify a pointer passed to a function, to understand their usage better. For brevity, I use the terms ptr-to-ptr and ref-to-ptr, respectively, to represent them. In this article, I'm not going to discuss how to use ptr-to-ptr as a 2-dimensional array or array of pointers. Please note we can use ptr-to-ptr in C and C++ but we can only use ref-to-ptr in C++.

Why We Need Them

When we use "pass by pointer" to pass a pointer to a function, only a copy of the pointer is passed to the function. We can say "pass by pointer", it is actually passing a pointer by value. In most cases, this does not present a problem. But, a problem arises when you modify the pointer inside the function. Instead of modifying the variable, you are only modifying a copy of the pointer and the original pointer remains unmodified, that is, it still points to the old variable. The code below demonstrates this behaviour.

//global variable
int g_One=1;
//function prototype
void func(int* pInt);

int main()
{
  int nvar=2;
  int* pvar=&nvar;
  func(pvar);
  std::cout<<*pvar<<std::endl;    //Will still show 2
  return 0;
}

void func(int* pInt)
{
  pInt=&g_One;
}

Syntax of Pointer-to-Pointer

This is how you call the function with a ptr-to-ptr parameter:

//function prototype
void func(int** ppInt);

int main()
{
  int nvar=2;
  int* pvar=&nvar;
  func(&pvar);
  ....
  return 0;
}

Let us see how to modify the pointer in the function using a ptr-to-ptr parameter

void func(int** ppInt)
{
  //Modify the pointer ppInt points to
  *ppInt=&g_One;
  //You can also allocate memory, depending on your requirements
  *ppInt=new int;
  //Modify the variable *ppInt points to
  **ppInt=3;
}

Let me summarize what all those dereferencing statements are:

  • ppInt is the ptr-to-ptr. We will never modify this because if we do, we'll lose our grip on the address of the pointer it is pointing to.
  • *ppInt is the pointed pointer. If we modify this, we are modifying the contents of the pointed pointer, which is an address and in the above example, pvar. In other words, we are effectively modifying what pvar points to.
  • **ppInt is the dereferenced twice variable which is what pvar points to.

Syntax of Reference-to-Pointer

Let us see how to modify a pointer in the function using a ref-to-ptr parameter.

//global variable
int g_One=1;
//function prototype
void func(int*& rpInt);

int main()
{
  int nvar=2;
  int* pvar=&nvar;
  func(pvar);
  ....
  return 0;
}
void func(int*& rpInt)
{
  //Modify what pvar is pointing to, to g_One
  rpInt=&g_One;
  //You can also allocate memory, depending on your requirements
  rpInt=new int;
  //Modify the variable rpInt points to
  *rpInt=3;
}

Now, let us look at how you called the function with the ref-to-ptr parameter:

You may wonder whether, in the above func(), the parameter rpInt is pointer to reference. Just take my word for it that it is called ref-to-ptr and it is ref-to-ptr.

Let me once again summarize what all those dereferencing statements are:

  • rpInt is the reference for the pointer, pvar in the above example.
  • *rpInt dereferences what pvar point to, so you get the variable the pointer, pvar is pointing to.

Syntax of tracking reference to a handle(C++/CLI)

Let us see how to modify a handle in C++/CLI function using the "tracking reference to a handle" parameter. This C++/CLI handle has nothing to do with Win32 HANDLEs and this handle is a reference to a managed object on the CLI heap. I use an object this time, instead of a Plain Old Data(POD)/primitive data/value type because you can only change a reference to an object.

//function prototype
void func(ClassA^% thObj);

int main()
{
  ClassA^ obj = gcnew ClassA;
  ClassA^ obj2=&obj;
  func(obj2);
  ....
  return 0;
}
void func(ClassA^% thObj)
{
  //Modify what obj2 is referencing, to g_obj
  thObj=g_obj; // g_obj is a global object.
  //You can instantiate a new class
  thObj=gcnew ClassA();
  //Modify the variable thObj is referencing, through a its member function, SetInt().
  thObj->SetInt(3);
}

Let me once again summarize what all those dereferencing statements are:

  • thObj is the tracking reference for the handle, obj2 in the above example.

Preference of One Over the Other

Now we have seen the syntax of ptr-to-ptr and ref-to-ptr. Are there any advantages of one over the other? I'm afraid not. The usage of one or both is just a personal preference for some programmers. Some who use ref-to-ptr say the syntax is "cleaner" while some who use ptr-to-ptr say that the ptr-to-ptr syntax makes it clearer to those reading the code just what you are doing.

Do Not Mistake Every Pointer-to-Pointer Argument

Do not mistake every ptr-to-ptr argument as purely ptr-to-ptr. An example would be to write int main(int argc, char *argv[]){...} as int main(int argc, char **argv){...} where **argv is actually an array of pointers. Be sure to check out the library documentation first!

Reference to Pointer Type (RTTI)

You cannot use RTTI to find out the type of ref-to-ptr. typeid() does not support reference types.

void test(int*& rpInt)
{
  std::cout << "type of *&rpInt: " << typeid(rpInt).name()
            << std::endl;    //will show int *
}

What Are Other Alternatives?

If you find that the ptr-to-ptr and ref-to-ptr syntax are rather hard to understand, you can just use the "return the pointer" method.

int* func()
{
  ....
  return new int;
}

Conclusion

You may ask whether you would ever use ptr-to-ptr and ref-to-ptr in your projects and whether it is necessary to know about them. Well, as developers, we use libraries and technologies that other people developed. One example would be that COM uses ptr-to-ptr to return an interface pointer using CoCreateInstance() and IUnknown::QueryInterface(). At some point in your developer career, you are definitely going to come across them. It is good to know them.

History

  • 2009/04/29 Updated the explanations and added tracking reference to a handle in C++/CLI
  • 2003/09/02 First release


About the Author

Wong Shao Voon

I guess I'll write here what I does in my free time, than to write an accolade of skills which I currently possess. I believe the things I does in my free time, say more about me.

When I am not working, I like to watch Japanese anime. I am also writing some movie script, hoping to see my own movie on the big screen one day.

I like to jog because it makes me feel good, having done something meaningful in the morning before the day starts.

I also writes articles for CodeGuru; I have a few ideas to write about but never get around writing because of hectic schedule.

Comments

  • Great

    Posted by MrCyclope on 09/26/2011 11:28am

    Short and clear :)

    Reply
  • Excellent article, keep on going. Thanks

    Posted by Gilam Roth on 12/30/2010 01:04pm

    Thanks for a short well describe excellent article. You are write about COM but also aboute using the ptr2ptr stuff. Larg projects will be a place that you'll must use it. My experience is that people prefear better the ptr2ptr notation then ref2ptr. It is easier to read and maintain. I think that there is a difference one of it you mention in the article and the other is the same difference between ptr to ref. That means extra care for null var passing.

    Reply
  • Great Attempt

    Posted by pjz_007 on 05/05/2009 07:20am

    This article is Great Attempt

    Reply
  • The article is updated

    Posted by CBasicNet on 04/28/2009 11:19pm

    You may read the article now. Thanks Brad!

    Reply
  • This article is not updated!

    Posted by CBasicNet on 04/28/2009 09:55pm

    It is still dated September 2, 2003. Please do not read this article yet until it is updated. Thank you!

    Reply
  • briely - good understandig

    Posted by 2faust on 08/07/2008 07:11am

    excellent

    Reply
  • It is precise and in short description and difference.

    Posted by Legacy on 09/10/2003 12:00am

    Originally posted by: dede

    Just great going ! In less word describes more.

    Reply
  • Another thing

    Posted by Legacy on 09/04/2003 12:00am

    Originally posted by: Per Nilsson

    Isn't the fact that a ptr may be NULL, but a ref can't also quite a big difference?

    What that implies I leave as an exercise for you to figure out...


    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • Email is the most common communication vehicle used by organizations of all shapes and sizes. Among the billions of email messages sent every day are sensitive information, critical requests, and other essential business data. IT staff bear the burden of ensuring the confidentiality, integrity, and availability of the information contained within the communication. This white paper explores the email security landscape, an assessment of the threats organizations face,  and the building blocks of an effective …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds