17

Possible Duplicate:
Common Uses For Pointers?

I am still learning the basics of C++ but I already know enough to do useful little programs.

I understand the concept of pointers and the examples I see in tutorials make sense to me. However, on the practical level, and being a (former) PHP developer, I am not yet confident to actually use them in my programs.

In fact, so far I have not felt the need to use any pointer. I have my classes and functions and I seem to be doing perfectly fine without using any pointer (let alone pointers to pointers). And I can't help feeling a bit proud of my little programs.

Still, I am aware that I am missing on one of C++'s most important feature, a double edged one: pointers and memory management can create havoc, seemingly random crashes, hard to find bugs and security holes... but at the same time, properly used, they must allow for clever and efficient programming.

So: do tell me what I am missing by not using pointers.

What are good scenarios where using pointers is a must?
What do they allow you to do that you couldn't do otherwise?
In which way to they make your programs more efficient?

And what about pointers to pointers???

[Edit: All the various answers are useful. One problem at SO is that we cannot "accept" more than one answer. I often wish I could. Actually, it's all the answers combined that help to understand better the whole picture. Thanks.]

Community
  • 1
  • 1
augustin
  • 14,373
  • 13
  • 66
  • 79
  • 1
    Outside of managing a resource, use a pointer to maintain non-owning access to something. And managing a resource (writing a SBRM class), to manage your data. (Which means respect The Rule of Three.) – GManNickG Oct 27 '10 at 04:46
  • 6
    You are missing the fact that we try and not use pointers in C++. The general use of pointers (and resource management problems) is a relic of C (not C++). Yes we still use pointers in C++ but they are burred away on the inside of objects and thus are tightly controlled you rarely see pointer flying around a program (just within the tightly controlled constraints of a class). – Martin York Oct 27 '10 at 05:22
  • 2
    Martin, sometimes I feel like we are programming in very different worlds. – Crashworks Oct 27 '10 at 05:25
  • If you use classes, you are implicitly using the `this` pointer ;-) – fredoverflow Oct 27 '10 at 05:46
  • @augustin: **Do you use references?** (E.g. if you want to allow a function to modify an object that you pass to it, how would you do that?) – j_random_hacker Oct 27 '10 at 10:06
  • @j_random_hacker :) Yes, coming from PHP, I am already familiar with passing arguments by reference. @FredOverflow :) Same with the this->bar thing. Those are the kind of pointers I am already familiar with. My question was more aimed at all the other uses of pointers, e.g. declaring a pointer myself. There are a lot of very good answers, already. Thanks. – augustin Oct 27 '10 at 10:22
  • @augustin: That's good. A pointer is exactly the same as a reference that can be made to refer to different things -- a "variable" reference. In the days of C, they were necessary for looping through linked lists and tree structures, and can still be used for that in C++, although there are now easier-to-use data structures (that still use them behind the scenes but hide the fact from the user). – j_random_hacker Oct 27 '10 at 10:39
  • @j_random_hacker: Also, a pointer can be null, while a reference can't be. – David Thornley Oct 27 '10 at 17:39
  • @Martin York: I assume you mean raw pointers. I use a lot of smart pointers, but fewer `*`s. – David Thornley Oct 27 '10 at 17:42
  • @Crashworks: You need to use the @ symbol or I will not get notified of your comments. Yes the C world is very different to the C++ world. If you are using pointers you are programming in what I refer to as `C` or `C with classes` but not `C++`. @David Thornley. Yes, I use smart pointers (but they are really objects (that happen to contain and manage RAW pointers)). – Martin York Oct 27 '10 at 20:59

11 Answers11

9

I use pointers when I want to give a class access to an object, without giving it ownership of that object. Even then, I can use a reference, unless I need to be able to change which object I am accessing and/or I need the option of no object, in which case the pointer would be NULL.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
8

This question has been asked on SO before. My answer from there:

I use pointers about once every six lines in the C++ code that I write. Off the top of my head, these are the most common uses:

  • When I need to dynamically create an object whose lifetime exceeds the scope in which it was created.
  • When I need to allocate an object whose size is unknown at compile time.
  • When I need to transfer ownership of an object from one thing to another without actually copying it (like in a linked list/heap/whatever of really big, expensive structs)
  • When I need to refer to the same object from two different places.
  • When I need to slice an array without copying it.
  • When I need to use compiler intrinsics to generate CPU-specific instructions, or work around situations where the compiler emits suboptimal or naive code.
  • When I need to write directly to a specific region of memory (because it has memory-mapped IO).
Community
  • 1
  • 1
Crashworks
  • 40,496
  • 12
  • 101
  • 170
  • That last point is only relevant with embedded or driver programming, and could easily be replaced with a reference. Otherwise it's a nice comprehensive list. – Mark Ransom Oct 27 '10 at 05:33
  • There are cases where drivers or operating systems sometimes just give you naked addresses for things, and I don't know any way to to seat a reference to an arbitrary address. For example, the OS function to get the destination for sound data on one popular game console literally has the prototype `uint64 AudioGetPortReadAddr( uint32 portNumber );` – Crashworks Oct 27 '10 at 05:56
  • +1 in general, but two concerns: It seems from your second line that pointers are the most common construct in the language (1/6 of the lines) while in many domains you can write perfectly good code without actually having a single pointer. When you need to refer to the same object from two places you have to decide between a pointer or a reference, and the later should be preferred if possible. – David Rodríguez - dribeas Oct 27 '10 at 07:46
  • 2
    ... an example where a pointer must be used in place of a reference is this: `int a,b,*c = &a; c = &b;` This cannot be implemented with a reference, as the reference would be bound to `a` at definition time and could not be *reseated* to refer to `b` later on. To complete the answer, one extra situation where pointers are a used is when passing optional arguments to a function, as pointers can be null, but references/values (of non pointer type) cannot. – David Rodríguez - dribeas Oct 27 '10 at 07:47
  • As David pointed out, the times I find myself using a pointer is often when I need to reseat (good term) the pointer in the course of decision logic in a function. The other situation, which also involves reseating, is when pointer arithmetic is being performed on an array of items. Like it or not, not everything is implemented in vectors and iterators. – Dan Oct 27 '10 at 14:43
  • The first point, i.e., "When I need to dynamically create an object whose lifetime exceeds the scope in which it was created.", is the main reason why I have to use (smart) pointers instead of reference. – EXP0 Oct 27 '10 at 14:59
7

Pointers are commonly used in C++. Becoming comfortable with them, will help you understand a broader range of code. That said if you can avoid them that is great, however, in time as your programs become more complex, you will likely need them even if only to interface with other libraries.

  • Primarily pointers are used to refer to dynamically allocated memory (returned by new).

  • They allow functions to take arguments that cannot be copied onto the stack either because they are too big or cannot be copied, such as an object returned by a system call. (I think also stack alignment, can be an issue, but too hazy to be confident.)

  • In embedded programing they are used to refer to things like hardware registers, which require that the code write to a very specific address in memory.

  • Pointers are also used to access objects through their base class interfaces. That is if I have a class B that is derived from class A class B : public A {}. That is an instance of the object B could be accessed as if it where class A by providing its address to a pointer to class A, ie: A *a = &b_obj;

  • It is a C idiom to use pointers as iterators on arrays. This may still be common in older C++ code, but is probably considered a poor cousin to the STL iterator objects.

  • If you need to interface with C code, you will invariable need to handle pointers which are used to refer to dynamically allocated objects, as there are no references. C strings are just pointers to an array of characters terminated by the nul '\0' character.

Once you feel comfortable with pointers, pointers to pointers won't seem so awful. The most obvious example is the argument list to main(). This is typically declared as char *argv[], but I have seen it declared (legally I believe) as char **argv.

The declaration is C style, but it says that I have array of pointers to pointers to char. Which is interpreted as a arbitrary sized array (the size is carried by argc) of C style strings (character arrays terminated by the nul '\0' character).

JoshD
  • 12,490
  • 3
  • 42
  • 53
Marc Butler
  • 1,346
  • 7
  • 13
  • 2
    +1 but it would be good to mention that references can do a lot of this work and are safer. – j_random_hacker Oct 27 '10 at 10:15
  • Thanks @j_random_hacker and everybody for commenting on the answers. Both answers and comments are useful. I'm still learning. – augustin Oct 27 '10 at 10:29
  • One clarification: C strings are terminated by the null \0 character, not the 0 character. – jram930 Oct 28 '10 at 13:23
  • @JRam930 Yes - I have updated to make that clearer based on your comment. – Marc Butler Oct 28 '10 at 17:28
  • @j_random_hacker: Yes i agree. I was disappointed to see mention of pointers to use base class interfaces instead of references. Or not mentioning a user 'should' use stl for memory 'most of the time'. I actually have done a number of projects without a single pointer by using references and stl. No ugly code or hackorey needed. –  Oct 31 '10 at 02:48
4

If you haven't felt a need for pointers, I wouldn't spend a lot of time worrying about them until a need arises.

That said, one of the primary ways pointers can contribute to more efficient programming is by avoiding copies of actual data. For example, let's assume you were writing a network stack. You receive an Ethernet packet to be processed. You successively pass that data up the stack from the "raw" Ethernet driver to the IP driver to the TCP driver to, say, the HTTP driver to something that processes the HTML it contains.

If you're making a new copy of the contents for each of those, you end up making at least four copies of the data before you actually get around to rendering it at all.

Using pointers can avoid a lot of that -- instead of copying the data itself, you just pass around a pointer to the data. Each successive layer of the network stack looks at its own header, and passes a pointer to what it considers the "payload" up to the next higher layer in the stack. That next layer looks at its own header, modifies the pointer to show what it considers the payload, and passes it on up the stack. Instead of four copies of the data, all four layers work with one copy of the real data.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

A big use for pointers is dynamic sizing of arrays. When you don't know the size of the array at compile time, you will need to allocate it at run-time.

int *array = new int[dynamicSize];

If your solution to this problem is to use std::vector from the STL, they use dynamic memory allocation behind the scenes.

Jason Iverson
  • 2,500
  • 1
  • 15
  • 15
  • 1
    I've found that `std::vector` is often even simpler than a smart pointer. Having that stuff hidden behind the scenes is a powerful abstraction, once you understand how it all works. That's the problem - to understand why something is so wonderful, you have to understand the alternative as well. – Mark Ransom Oct 27 '10 at 05:08
  • 2
    Sorry but I have to -1 this. This is the *perfect* example of where pointers should no longer be used. `std:vector` is just better. Answers like this only obscure the places where pointers really are invaluable. – j_random_hacker Oct 27 '10 at 09:58
  • @j_random_hacker You can't generalize it away with a blanket statement stating that you should always use a std::vector. There will always be situations when the overhead of std::vector is unneeded. Not everyone works on the high level, some of us deal with a lot of low level implementations for optimizations on low memory hardware. I will admit that 98% of the time I use std::vector (or my own optimized version), but there are situations that I'd still use the "old school" way of doing it. – Jason Iverson Oct 27 '10 at 14:55
  • 1
    Agreed it can be useful on about 2% of occasions for that, but the question asker is a C++ newbie and we should not be recommending using pointers for this bug-intensive approach when there are now safer alternatives AND other, better uses to which pointers can be put. (BTW remember the bulk of the overhead comes from the dynamic allocation itself and not from `std::vector` -- you would be better served writing an allocator and using `std::vector` anyway.) – j_random_hacker Oct 28 '10 at 00:26
  • What overhead? You still shouldn't be in a position to `delete` something. If you claim overhead, that at the least just put it in a `unique_ptr`, which has none. – GManNickG Oct 28 '10 at 17:40
2

There are several scenarios where pointers are required:

  • If you are using Abstract Base Classes with virtual methods. You can hold a std::vector and loop through all these objects and call a virtual method. This REQUIRES pointers.
  • You can pass a pointer to a buffer to a method reading from a file etc.
  • You need a lot of memory allocated on the heap.

It's a good thing to care about memory problems right from the start. So if you start using pointers, you might as well take a look at smart pointers, like boost's shared_ptr for example.

Philipp
  • 11,549
  • 8
  • 66
  • 126
  • 1
    Uggg.. smart pointers.. boost.. Ugh. I don't think smart pointers are a good place for people to start. Oh and not everyone can use boost. It pre-supposes STL. I loath STL because I can't use it, and it's on every last "do you know c++" test. – baash05 Oct 27 '10 at 04:39
  • 2
    Smart pointers can save you a lot of headaches and make your code more expressive by telling the reader who is owning the object pointed to. If he can't use boost, he doesn't have to, but I suggested "he might take a look at it". So I don't think it's a bad adivice... – Philipp Oct 27 '10 at 04:42
  • 3
    @baash: I accidentally upvoted your comment. Use smart pointers, use SBRM/RAII, and wrap your resources, or you're not writing good code. – GManNickG Oct 27 '10 at 04:43
  • The problem with "smart" pointers is that there are a half-dozen different varieties of them, so every time you want a pointer you have to stop and think about what kind to use. – Gabe Oct 27 '10 at 04:48
  • 3
    @Gabe, if you're trying to program without thinking, you're using the wrong language. Or maybe the wrong profession. – Mark Ransom Oct 27 '10 at 04:52
  • 3
    I would concentrate on few important pointers (shared, scoped, weak). Then in fact this might be a good thing: If you don't use smart pointers you are not forced to think about "who is owning this pointer?" which might get you into memory leaks or double deleted objects! After using them for a while, this won't be a problem anymore. – Philipp Oct 27 '10 at 04:52
  • Mark: Every moment I spend thinking about how variables will be ref-counted is a moment I spend not thinking about my algorithm. Maybe I'm just not smart enough to use smart pointers. – Gabe Oct 27 '10 at 05:30
  • I keep it simple.. I create and I destroy. new and delete have always worked for me.. When I create, I just make sure all my closing branches clean up. It's insanely easy to do. I don't get why smart pointers are needed.. They might make something easy, easier, but I prefer simpler to easier. – baash05 Oct 27 '10 at 05:52
  • GMan.. purposely upvoted your comment. The research value alone will make you far under "pointed" :) – baash05 Oct 27 '10 at 05:54
2

What are good scenarios where using pointers is a must?
Interviews. Implement strcpy.

What do they allow you to do that you couldn't do otherwise?
Use of inheritance hierarchy. Data structures like Binary trees.

In which way to they make your programs more efficient?
They give more control to the programmer, for creating and deleting resources at run time.

And what about pointers to pointers???
A frequently asked interview question. How will you create two dimensional array on heap.

Manoj R
  • 3,197
  • 1
  • 21
  • 36
  • 1
    Considered -1ing, since the question is tagged C++ and no C++ programmer should have to implement `strcpy()`, but really that -1 belongs to the stupid interviewer. (The same *should* be true of creating a 2D heap array, but tragically this can't be done efficienctly < C++0x.) – j_random_hacker Oct 27 '10 at 10:11
1

A pointer has a special value, NULL, that reference's won't. I use pointers wherever NULL is a valid and useful value.

Arun
  • 19,750
  • 10
  • 51
  • 60
1

I just want to say that i rarely use pointers. I use references and stl objects (deque, list, map, etc).

A good idea is when you need to return an object where the calling function should free or when you dont want to return by value.

 List<char*>* fileToList(char*filename) { //dont want to pass list by value
 ClassName* DataToMyClass(DbConnectionOrSomeType& data) { 
 //alternatively you can do the below which doesnt require pointers
 void DataToMyClass(DbConnectionOrSomeType& data, ClassName& myClass) { 

Thats pretty much the only situation i use but i am not thinking that hard. Also if i want a function to modify a variable and cant use the return value (say i need more then one)

 bool SetToFiveIfPositive(int**v) {
  • 1
    Return a smart pointer and the calling function won’t have to free it. Alternatively, in C++0x just return the `list` by value. It will be moved, not copied. – Nate Oct 27 '10 at 06:07
  • 1
    +1, prefer references and STL containers wherever possible. – j_random_hacker Oct 27 '10 at 10:13
  • @Nate: I never, ever had to use a smart pointer. Also smart pointers need regular pointers so i rather discuss that instead. You mean C++0x can return rvalue instead? yeah that would work. ATM we cant o that in most compilers which is unfortunate. –  Oct 27 '10 at 16:09
0

You can use them for linked lists, trees, etc. They're very important data structures.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • Though you'd be using the linked list and tree. You mean use them to *implement* the container that's going to *manage* the structure that we're going to use. – GManNickG Oct 27 '10 at 04:44
0

In general, pointers are useful as they can hold the address of a chunk of memory. They are especially useful in some low level drivers where they are efficiently used to operate on a piece of memory byte by byte. They are most powerful invention that C++ inherits from C.

As to pointer to pointer, here is a "hello-world" example showing you how to use it.

#include <iostream>

void main()
{
    int i = 1;
    int j = 2;

    int *pInt = &i;                 // "pInt" points to "i"

    std::cout<<*pInt<<std::endl;    // prints: 1

    *pInt = 6;                      // modify i, i = 6

    std::cout<<i<<std::endl;        // prints: 6

    int **ppInt = &pInt;            // "ppInt" points to "pInt"

    std::cout<<**ppInt<<std::endl;  // prints: 6

    **ppInt = 8;                    // modify i, i = 8

    std::cout<<i<<std::endl;        // prints: 8

    *ppInt = &j;                    // now pInt points to j

    *pInt = 10;                     // modify j, j = 10

    std::cout<<j<<std::endl;        // prints: 10
}

As we see, "pInt" is a pointer to integer which points to "i" at the beginning. With it, you can modify "i". "ppInt" is a pointer to pointer which points to "pInt". With it, you can modify "pInt" which happens to be an address. As a result, "*ppInt = &j" makes "pInt" points to "j" now. So we have all the results above.

Eric Z
  • 14,327
  • 7
  • 45
  • 69