1718

I'm coming from a Java background and have started working with objects in C++. But one thing that occurred to me is that people often use pointers to objects rather than the objects themselves, for example this declaration:

Object *myObject = new Object;

rather than:

Object myObject;

Or instead of using a function, let's say testFunc(), like this:

myObject.testFunc();

we have to write:

myObject->testFunc();

But I can't figure out why should we do it this way. I would assume it has to do with efficiency and speed since we get direct access to the memory address. Am I right?

artm
  • 16,141
  • 4
  • 27
  • 46
gEdringer
  • 14,619
  • 3
  • 12
  • 24
  • 138
    If you don't see a reason to use pointers, don't. Prefer objects. Prefer objects before unique_ptr before shared_ptr before raw pointers. – stefan Mar 03 '14 at 12:00
  • 124
    note: in java, everything(except basic types) is a pointer. so you rather should ask the opposite: why do I need simple objects? – Karoly Horvath Mar 03 '14 at 12:01
  • 127
    Note that, in Java, pointers are hidden by syntax. In C++, the difference between a pointer and a non-pointer is made explicit in code. Java uses pointers everywhere. – Daniel Martín Mar 03 '14 at 12:04
  • 5
    In C++11 you need pointers significantly less often. – Marc Claesen Mar 03 '14 at 15:00
  • 8
    @KarolyHorvath [They're close, but not the same](http://programmers.stackexchange.com/a/141838/27881) – Izkata Mar 03 '14 at 15:48
  • 233
    Close as *too broad*? Seriously? Please people, note that this Java++ way of programming is **very common and one of the most important problems on the C++ community**. It should be treated seriously. – Manu343726 Mar 03 '14 at 22:53
  • 4
    Related (but not a duplicate): *[C++ objects: When should I use a pointer or a reference?](http://stackoverflow.com/questions/4288030/c-objects-when-should-i-use-pointer-or-reference/4288340#4288340)* – Peter Mortensen Mar 05 '14 at 19:25
  • @PeterMortensen [I thought the same thing the other day](http://stackoverflow.com/questions/21256252/force-the-compiler-to-ignore-some-lines-in-the-program#comment32047447_21256252), but alas, I was wrong. Perhaps you are, too. =) – jpmc26 Mar 06 '14 at 01:33
  • 1
    @Manu343726 if you think its too broad.. and maybe a little conceptual perhaps it belongs on programmers.stackexchange.com ...fwiw – HashHazard Mar 09 '14 at 01:03
  • This question covers a lot of the same territory, but with an awareness of modern pointer management: [What is the objective of scoped pointer?](http://stackoverflow.com/questions/10729522/why-scoped-pointers-in-boost) – Brent Bradburn Mar 09 '14 at 03:54
  • 1
    What do you think you are doing in Java? – Nils Mar 14 '14 at 10:39
  • 1
    A Java programmer doesn't know that in Java every object typed thing is implicitly by reference? – Warren P Mar 14 '14 at 10:57
  • 1
    Protip: Use make_unique (which isn't standard but well practiced) or make_shared instead of using the new keyword. Naked ptrs are bad. http://herbsutter.com/gotw/_102/ –  Mar 14 '14 at 22:53
  • @DanielMarin or rather, Java "references" are pointers with deleted arithmetic operators. – user877329 Dec 24 '15 at 09:48
  • 26
    Why should I use a house address when I could just use the house itself? Instead of telling Amazon to send my package to 123 Nowhere St, I just bring my house to the warehouse, they put my purchases in it, and I bring it back. – user253751 Feb 10 '16 at 23:57
  • I was going to say the same things as @immibis, because a a pointer is lighter than an object – Brian Joseph Spinos Apr 01 '17 at 23:14
  • 2
    @immibis bring a copy of your house to the warehouse, return another copy and assign it to your house and support the construction industry. – wonko realtime Apr 04 '19 at 11:59
  • This question combines asking about heap vs stack allocation (the "pointer" declaration uses new) and asking why pointers would be used rather than referring to objects by name. The question/answers mention c++ references very little also. – bobsburner Mar 23 '20 at 12:14
  • The simple reason is that you only have access to the object in the scope in which it was declared, and any non-trivial program has thousands of other scopes in which you need the object. – user207421 Apr 26 '20 at 04:03

22 Answers22

1680

It's very unfortunate that you see dynamic allocation so often. That just shows how many bad C++ programmers there are.

In a sense, you have two questions bundled up into one. The first is when should we use dynamic allocation (using new)? The second is when should we use pointers?

The important take-home message is that you should always use the appropriate tool for the job. In almost all situations, there is something more appropriate and safer than performing manual dynamic allocation and/or using raw pointers.

Dynamic allocation

In your question, you've demonstrated two ways of creating an object. The main difference is the storage duration of the object. When doing Object myObject; within a block, the object is created with automatic storage duration, which means it will be destroyed automatically when it goes out of scope. When you do new Object(), the object has dynamic storage duration, which means it stays alive until you explicitly delete it. You should only use dynamic storage duration when you need it. That is, you should always prefer creating objects with automatic storage duration when you can.

The main two situations in which you might require dynamic allocation:

  1. You need the object to outlive the current scope - that specific object at that specific memory location, not a copy of it. If you're okay with copying/moving the object (most of the time you should be), you should prefer an automatic object.
  2. You need to allocate a lot of memory, which may easily fill up the stack. It would be nice if we didn't have to concern ourselves with this (most of the time you shouldn't have to), as it's really outside the purview of C++, but unfortunately, we have to deal with the reality of the systems we're developing for.

When you do absolutely require dynamic allocation, you should encapsulate it in a smart pointer or some other type that performs RAII (like the standard containers). Smart pointers provide ownership semantics of dynamically allocated objects. Take a look at std::unique_ptr and std::shared_ptr, for example. If you use them appropriately, you can almost entirely avoid performing your own memory management (see the Rule of Zero).

Pointers

However, there are other more general uses for raw pointers beyond dynamic allocation, but most have alternatives that you should prefer. As before, always prefer the alternatives unless you really need pointers.

  1. You need reference semantics. Sometimes you want to pass an object using a pointer (regardless of how it was allocated) because you want the function to which you're passing it to have access that that specific object (not a copy of it). However, in most situations, you should prefer reference types to pointers, because this is specifically what they're designed for. Note this is not necessarily about extending the lifetime of the object beyond the current scope, as in situation 1 above. As before, if you're okay with passing a copy of the object, you don't need reference semantics.

  2. You need polymorphism. You can only call functions polymorphically (that is, according to the dynamic type of an object) through a pointer or reference to the object. If that's the behavior you need, then you need to use pointers or references. Again, references should be preferred.

  3. You want to represent that an object is optional by allowing a nullptr to be passed when the object is being omitted. If it's an argument, you should prefer to use default arguments or function overloads. Otherwise, you should preferably use a type that encapsulates this behavior, such as std::optional (introduced in C++17 - with earlier C++ standards, use boost::optional).

  4. You want to decouple compilation units to improve compilation time. The useful property of a pointer is that you only require a forward declaration of the pointed-to type (to actually use the object, you'll need a definition). This allows you to decouple parts of your compilation process, which may significantly improve compilation time. See the Pimpl idiom.

  5. You need to interface with a C library or a C-style library. At this point, you're forced to use raw pointers. The best thing you can do is make sure you only let your raw pointers loose at the last possible moment. You can get a raw pointer from a smart pointer, for example, by using its get member function. If a library performs some allocation for you which it expects you to deallocate via a handle, you can often wrap the handle up in a smart pointer with a custom deleter that will deallocate the object appropriately.

Rafael Beckel
  • 1,688
  • 4
  • 22
  • 32
Joseph Mansfield
  • 100,738
  • 18
  • 225
  • 303
  • 86
    "You need the object to outlive the current scope." -- An additional note about this: there are cases where it seems like you need the object to outlive the current scope, but you really don't. If you put your object inside a vector, for example, the object will be copied (or moved) into the vector, and the original object is safe to destroy when its scope ends. –  Mar 03 '14 at 12:03
  • "You need the object to outlive the current scope" - One can also return the object, if possible. Although it's a copy of the object that is returned, the code is pretty neat. Unless the copying is heavy, I tend to return the object (if possible and makes logical sense). – rajatkhanduja Mar 03 '14 at 12:04
  • 25
    Remember that s/copy/move/ in many places now. Returning an object definitely does not imply a move. You should also note that accessing an object through a pointer is orthogonal to how it was created. – Puppy Mar 03 '14 at 12:10
  • 3
    @rajatkhanduja He made that distinction: in the parentheses of his point 1 ("that specific object...not a copy of it"). Technically, this means "when identity is significant". – James Kanze Mar 03 '14 at 13:22
  • 1
    Your point 1 probably represents more than 90% of the cases. You're point 2 is usually covered by pre-existing classes, like `std::vector`. And you've missed an important point 3: you need polymorphism on the declared type. And of course, the paragraph which follows the points doesn't hold for point 1, which is the most frequent case. – James Kanze Mar 03 '14 at 13:24
  • 1
    @JamesKanze I think the paragraph afterwards applies to both points, because I was specifically talking about dynamic allocation. That might have been confusing because the question title asks about pointers vs non-pointers, but I was reinterpreting it as dynamic vs automatic because I think that's what they were really asking about. I've added some more details about other uses of pointers in general though. – Joseph Mansfield Mar 03 '14 at 14:46
  • 4
    Also, there are libraries, like Qt, having their own weird memory management system. In such cases, one has to use raw (and not smart) pointers. – BЈовић Mar 03 '14 at 15:06
  • Word to the wise: one more edit and this answer turns into a community wiki! It [happened to me](http://meta.stackexchange.com/q/188364/192808) on one high scoring answer. – TemplateRex Mar 03 '14 at 17:32
  • 1
    @DavidConrad For the most part, embrace copying and moving. If you want to pass an object to a function and it won't be modified or copied, pass it by `const` reference. – Joseph Mansfield Mar 03 '14 at 19:14
  • 16
    I miss an explicit reference to RAII on this answer. C++ is all (almost all) about resource management, and RAII is the way to do it on C++ (And the main problem which raw pointers generate: Breaking RAII) – Manu343726 Mar 03 '14 at 23:01
  • 2
    I'd add "to interface with C code" to the reasons to use pointers - this is often via callbacks that take function pointers and void* data pointers. – Michael Anderson Mar 04 '14 at 05:32
  • 1
    Might be worth adding that, historically, pointers were also used for instantiating data structures where you are unsure of the size of them prior to compilation. These days (and, frankly, not long after C++ was officially released), the STL types cover that eventuality, but it does also explain why programmers became accustomed to always allocating to pointers to create the most amount of flexibility. – Sean Duggan Mar 04 '14 at 14:17
  • I don't really get the 'use smart pointers everywhere' trend. C++11 is not even available everywhere. Also, in a recent program, I used reference members where it was possible and pointer members otherwise. It became increasingly difficult to remember where I used which. – marczellm Mar 04 '14 at 22:55
  • 3
    @marczellm Well of course you can only use C++11's smart pointers if you have access to a C++11 compiler - and when you do, you *should* use them. The important aspect of smart pointers is that they help with the single-responsibility principle. Their responsibility is memory management, to provide some kind of ownership semantics for dynamic objects. That means your own classes don't need to bother care about memory management and can focus on their own responsibilities. – Joseph Mansfield Mar 04 '14 at 22:58
  • 1
    It would be helpful if you describe the stack and heap, and the differences between them. Understanding these concepts helps explain the 'why' behind all this. – Peter Mar 05 '14 at 07:14
  • 11
    Smart pointers existed before C++11, e.g. boost::shared_ptr and boost::scoped_ptr. Other projects have their own equivalent. You can't get move semantics, and std::auto_ptr's assign is flawed, so C++11 improves things, but the advice is still good. (And a sad nitpick, it's not enough to have access to _a_ C++11 compiler, it's necessary that all the compilers you might possibly want your code to work with support C++11. Yes, Oracle Solaris Studio, I'm looking at you.) – armb Mar 05 '14 at 15:29
  • 3
    "It's very unfortunate that you see dynamic allocation so often. That just shows how many bad C++ programmers there are." Is that really the case? Some languages (Objective-C) don't even allow you to allocate objects non-dynamically. If the downside for most use cases isn't that significant, why not simply do everything in a consistent manner? – Archagon Mar 07 '14 at 22:30
  • 1
    @Archagon I think the downside is often pretty significant. If there's a better way to do it using modern C++ idioms, they should be used. It makes it less confusing and safer for everybody. – Joseph Mansfield Mar 07 '14 at 22:47
  • Great answer, question though: using `Object myObject;` can only use the default constructor, ie `Object();`, so one would have to use `new Object(param1,etc..)` to access the overloaded constructors, right? – MDMoore313 Mar 08 '14 at 02:49
  • 5
    This answer is very C++11-centric and makes a ridiculous accusation in the very first sentence. I guess all those people that wrote MySQL, Webkit, Gecko and hundreds of millions of lines of proprietary code through the decades were all bad programmers. – Daniel S. Mar 09 '14 at 08:41
  • 2
    PS: I would like an example of a large, mature C++ codebase where -> is not the dominant operator to access data. – Daniel S. Mar 09 '14 at 08:44
  • In paragraph on why you'd need pointers, only number 3 and 5 are really relevant and cannot be done with references. I know this is stated, except in 4. – kebs Mar 09 '14 at 10:37
  • 7
    @MDMoore313 You can write `Object myObject(param1, etc...)` – user000001 Mar 09 '14 at 14:41
  • 1
    The point isn't how obvious that maxim is, the point is that even when the maxim IS obvious, the way to select what is appropriate is, with most languages, and C++ being no exception, rather more complicated. This answer does a good job of discussing some of the cases where a pointer or reference (as opposed to an object on the stack) might be useful. Since objects on the stack do not exist in java, the OP is obviously in need of such tutoring. – Warren P Mar 14 '14 at 11:18
  • 2
    @jwg It's not obvious to everybody that they should even consider the appropriateness of a tool. Some tools are more appropriate than others. – Joseph Mansfield Mar 14 '14 at 13:25
  • " Sometimes you want to pass an object using a pointer (regardless of how it was allocated) because you want the function to which you're passing it to have access that that specific object (not a copy of it). " In c++ I thought it passes objects by passing the address implicitly. If so your statement here is wrong. – NDEthos Sep 21 '14 at 02:32
  • 1
    @NicolasEdwards In C++, objects are passed by value by default. That is, they're copied. If you need reference semantics instead, you need to use either references or pointers (preferably references). – Joseph Mansfield Sep 21 '14 at 09:07
  • @Joseph Mansfield Yes, they are passed by value, but isn't the value the address of the object and not the whole object itself? – NDEthos Sep 21 '14 at 19:28
  • 3
    @NicolasEdwards Nope, it's the object itself that is copied. Perhaps you're thinking of Java, where everything is a reference that you copy around? – Joseph Mansfield Sep 21 '14 at 19:37
  • Which practice is better to use for creating linked lists? I'm trying to use each object of a class as elements of a linked list. – Noobification Oct 26 '14 at 00:57
  • It would appear that std::optional has made its way into the standard for c++17. – violet_white Dec 30 '16 at 22:21
  • @Remian8985 *"Which practice is better to use for creating linked lists"* - Um... `std::list<>` is how you do that, hence none of these answers/questions are relevant. – WhozCraig Oct 29 '19 at 20:16
  • "It's very unfortunate that you see dynamic allocation so often". cuz most books/tutorials don't emphasize the point. This answer is an eye opener to me - something I was always wondering why. – curious Jun 06 '20 at 21:44
  • I can't define an object of same class as member of class. https://stackoverflow.com/q/2706129/11212208 They say I need to use pointers. Isn't there any alternative? – Tojrah Jul 05 '20 at 16:37
180

There are many use cases for pointers.

Polymorphic behavior. For polymorphic types, pointers (or references) are used to avoid slicing:

class Base { ... };
class Derived : public Base { ... };

void fun(Base b) { ... }
void gun(Base* b) { ... }
void hun(Base& b) { ... }

Derived d;
fun(d);    // oops, all Derived parts silently "sliced" off
gun(&d);   // OK, a Derived object IS-A Base object
hun(d);    // also OK, reference also doesn't slice

Reference semantics and avoiding copying. For non-polymorphic types, a pointer (or a reference) will avoid copying a potentially expensive object

Base b;
fun(b);  // copies b, potentially expensive 
gun(&b); // takes a pointer to b, no copying
hun(b);  // regular syntax, behaves as a pointer

Note that C++11 has move semantics that can avoid many copies of expensive objects into function argument and as return values. But using a pointer will definitely avoid those and will allow multiple pointers on the same object (whereas an object can only be moved from once).

Resource acquisition. Creating a pointer to a resource using the new operator is an anti-pattern in modern C++. Use a special resource class (one of the Standard containers) or a smart pointer (std::unique_ptr<> or std::shared_ptr<>). Consider:

{
    auto b = new Base;
    ...       // oops, if an exception is thrown, destructor not called!
    delete b;
}

vs.

{
    auto b = std::make_unique<Base>();
    ...       // OK, now exception safe
}

A raw pointer should only be used as a "view" and not in any way involved in ownership, be it through direct creation or implicitly through return values. See also this Q&A from the C++ FAQ.

More fine-grained life-time control Every time a shared pointer is being copied (e.g. as a function argument) the resource it points to is being kept alive. Regular objects (not created by new, either directly by you or inside a resource class) are destroyed when going out of scope.

Community
  • 1
  • 1
TemplateRex
  • 65,583
  • 16
  • 147
  • 283
  • 18
    *"Creating a pointer to a resource using the new operator is an anti-pattern"* I think you could even enhance that to *having a raw pointer own something is an anti-pattern*. Not only the creation, but passing raw pointers as arguments or return values implying ownership transfer IMHO is deprecated since `unique_ptr`/move semantics – dyp Mar 03 '14 at 12:29
  • 5
    Using smart pointers everywhere is an anti-pattern. There are a few special cases where it is applicable, but most of the time, the same reason which argue for dynamic allocation (arbitrary lifetime) argue against any of the usual smart pointers as well. – James Kanze Mar 03 '14 at 13:26
  • 2
    @JamesKanze I didn't mean to imply that smart pointers should be used everywhere, just for ownership, and also that raw pointers should not be used for ownership, but only for views. – TemplateRex Mar 03 '14 at 13:28
  • What's the difference between `fun(b)` and `hun(b)` in your example? I didn't find any but you state there is. Did you need a different variable (like a pointer)? – Thomas Matthews Mar 03 '14 at 14:15
  • @ThomasMatthews I just wanted to point out that `hun(b)` takes a reference to `b`, not a copy. Some style guides (Google) forbid this and require `gun(&b)` because `hun(b)` requires knowledge of the signature to know if an argument can be modified. – TemplateRex Mar 03 '14 at 14:21
  • 2
    @TemplateRex That seems slightly silly given that `hun(b)` also requires knowledge of the signature unless you're fine with not knowing that you supplied the wrong type until compilation. While the reference issue usually won't get caught at compile time and would take more effort to debug, if you're checking the signature to make sure the arguments are right you'll also be able to see if any of the arguments are references so the reference bit becomes something of a non-problem (especially when using IDEs or text editors that show the signature of a selected functions). Also, `const&`. – JAB Mar 03 '14 at 16:04
  • @JAB agreed: by-value and by-const-ref look and behave the same but for copying; by-ptr and by-non-const-ref behave the same but the behavior of the latter is not obvious from the call site alone. That's the (admittedly weak) rationale for Google's style rule. – TemplateRex Mar 03 '14 at 17:31
  • @TemplateRex: Google's rule also fails when passing a non-const pointer to the next function. fun(&obj) calls fun2(obj). No address-of on that nested call, might as well be a reference. – Zan Lynx Mar 05 '14 at 22:17
  • 1
    @James "Using smart pointers everywhere is an anti-pattern." You mean needless heap allocation, or the smart pointers themselves? – Max Barraclough Apr 11 '18 at 11:28
  • I think it would be useful to edit the answer and instead of "Polymorphic behavior", use some kind of term relative to Dynamic Polymorphism. You can get polymorphic behavior by using function overloading, mixins and CRTP too. – ashrasmun Feb 26 '19 at 14:51
  • @JamesKanze Re "Using smart pointers everywhere is an anti-pattern"; An astonishing statement. Consensus on SO seems to be to use smart pointers throughout. This answer is an example. What is it that makes smart pointers, as you say, more unsuitable for managing object lifetime than raw pointers? I always thought they are better suited; indeed, they have been designed to aid in managing lifetime. I'm genuinely curious to hear your expert opinion. I may make this a question (because such a discussion exceeds the scope of comments), just say so. – Peter - Reinstate Monica Jun 29 '20 at 09:27
  • @Peter-ReinstateMonica It depends somewhat on the context, but usually, if you're using pointers (instead of values), you don't want the lifetime of the object to depend whether someone is holding a pointer to it or not: the object represents some specific entity, which has it's own lifetime, defined by the object's semantics. I'd be more nuanced about this today, but smart pointers aren't a silver bullet; the std::shared_ptr is even an invitation to dangling pointers and multiple deletions of the same object. – James Kanze Aug 31 '20 at 13:53
136

There are many excellent answers to this question, including the important use cases of forward declarations, polymorphism etc. but I feel a part of the "soul" of your question is not answered - namely what the different syntaxes mean across Java and C++.

Let's examine the situation comparing the two languages:

Java:

Object object1 = new Object(); //A new object is allocated by Java
Object object2 = new Object(); //Another new object is allocated by Java

object1 = object2; 
//object1 now points to the object originally allocated for object2
//The object originally allocated for object1 is now "dead" - nothing points to it, so it
//will be reclaimed by the Garbage Collector.
//If either object1 or object2 is changed, the change will be reflected to the other

The closest equivalent to this, is:

C++:

Object * object1 = new Object(); //A new object is allocated on the heap
Object * object2 = new Object(); //Another new object is allocated on the heap
delete object1;
//Since C++ does not have a garbage collector, if we don't do that, the next line would 
//cause a "memory leak", i.e. a piece of claimed memory that the app cannot use 
//and that we have no way to reclaim...

object1 = object2; //Same as Java, object1 points to object2.

Let's see the alternative C++ way:

Object object1; //A new object is allocated on the STACK
Object object2; //Another new object is allocated on the STACK
object1 = object2;//!!!! This is different! The CONTENTS of object2 are COPIED onto object1,
//using the "copy assignment operator", the definition of operator =.
//But, the two objects are still different. Change one, the other remains unchanged.
//Also, the objects get automatically destroyed once the function returns...

The best way to think of it is that -- more or less -- Java (implicitly) handles pointers to objects, while C++ may handle either pointers to objects, or the objects themselves. There are exceptions to this -- for example, if you declare Java "primitive" types, they are actual values that are copied, and not pointers. So,

Java:

int object1; //An integer is allocated on the stack.
int object2; //Another integer is allocated on the stack.
object1 = object2; //The value of object2 is copied to object1.

That said, using pointers is NOT necessarily either the correct or the wrong way to handle things; however other answers have covered that satisfactorily. The general idea though is that in C++ you have much more control on the lifetime of the objects, and on where they will live.

Take home point -- the Object * object = new Object() construct is actually what is closest to typical Java (or C# for that matter) semantics.

Community
  • 1
  • 1
Gerasimos R
  • 1,878
  • 1
  • 10
  • 19
  • 2
    `Object object1 = new Object(); Object object2 = new Object();` is very bad code. The second new or the second Object constructor may throw, and now object1 is leaked. If you are using raw `new`s, you should wrap `new`ed objects in RAII wrappers ASAP. – PSkocik Feb 11 '16 at 15:52
  • 9
    Indeed, it would be if this was a program, and nothing else was going on around it. Thankfully, this is just an explanation snippet showing how a Pointer in C++ behaves - and one of the few places where a RAII object cannot be substituted for a raw pointer, is studying and learning about raw pointers... – Gerasimos R Feb 18 '16 at 19:07
85

Preface

Java is nothing like C++, contrary to hype. The Java hype machine would like you to believe that because Java has C++ like syntax, that the languages are similar. Nothing can be further from the truth. This misinformation is part of the reason why Java programmers go to C++ and use Java-like syntax without understanding the implications of their code.

Onwards we go

But I can't figure out why should we do it this way. I would assume it has to do with efficiency and speed since we get direct access to the memory address. Am I right?

To the contrary, actually. The heap is much slower than the stack, because the stack is very simple compared to the heap. Automatic storage variables (aka stack variables) have their destructors called once they go out of scope. For example:

{
    std::string s;
}
// s is destroyed here

On the other hand, if you use a pointer dynamically allocated, its destructor must be called manually. delete calls this destructor for you.

{
    std::string* s = new std::string;
}
delete s; // destructor called

This has nothing to do with the new syntax prevalent in C# and Java. They are used for completely different purposes.

Benefits of dynamic allocation

1. You don't have to know the size of the array in advance

One of the first problems many C++ programmers run into is that when they are accepting arbitrary input from users, you can only allocate a fixed size for a stack variable. You cannot change the size of arrays either. For example:

char buffer[100];
std::cin >> buffer;
// bad input = buffer overflow

Of course, if you used an std::string instead, std::string internally resizes itself so that shouldn't be a problem. But essentially the solution to this problem is dynamic allocation. You can allocate dynamic memory based on the input of the user, for example:

int * pointer;
std::cout << "How many items do you need?";
std::cin >> n;
pointer = new int[n];

Side note: One mistake many beginners make is the usage of variable length arrays. This is a GNU extension and also one in Clang because they mirror many of GCC's extensions. So the following int arr[n] should not be relied on.

Because the heap is much bigger than the stack, one can arbitrarily allocate/reallocate as much memory as he/she needs, whereas the stack has a limitation.

2. Arrays are not pointers

How is this a benefit you ask? The answer will become clear once you understand the confusion/myth behind arrays and pointers. It is commonly assumed that they are the same, but they are not. This myth comes from the fact that pointers can be subscripted just like arrays and because of arrays decay to pointers at the top level in a function declaration. However, once an array decays to a pointer, the pointer loses its sizeof information. So sizeof(pointer) will give the size of the pointer in bytes, which is usually 8 bytes on a 64-bit system.

You cannot assign to arrays, only initialize them. For example:

int arr[5] = {1, 2, 3, 4, 5}; // initialization 
int arr[] = {1, 2, 3, 4, 5}; // The standard dictates that the size of the array
                             // be given by the amount of members in the initializer  
arr = { 1, 2, 3, 4, 5 }; // ERROR

On the other hand, you can do whatever you want with pointers. Unfortunately, because the distinction between pointers and arrays are hand-waved in Java and C#, beginners don't understand the difference.

3. Polymorphism

Java and C# have facilities that allow you to treat objects as another, for example using the as keyword. So if somebody wanted to treat an Entity object as a Player object, one could do Player player = Entity as Player; This is very useful if you intend to call functions on a homogeneous container that should only apply to a specific type. The functionality can be achieved in a similar fashion below:

std::vector<Base*> vector;
vector.push_back(&square);
vector.push_back(&triangle);
for (auto& e : vector)
{
     auto test = dynamic_cast<Triangle*>(e); // I only care about triangles
     if (!test) // not a triangle
        e.GenericFunction();
     else
        e.TriangleOnlyMagic();
}

So say if only Triangles had a Rotate function, it would be a compiler error if you tried to call it on all objects of the class. Using dynamic_cast, you can simulate the as keyword. To be clear, if a cast fails, it returns an invalid pointer. So !test is essentially a shorthand for checking if test is NULL or an invalid pointer, which means the cast failed.

Benefits of automatic variables

After seeing all the great things dynamic allocation can do, you're probably wondering why wouldn't anyone NOT use dynamic allocation all the time? I already told you one reason, the heap is slow. And if you don't need all that memory, you shouldn't abuse it. So here are some disadvantages in no particular order:

  • It is error-prone. Manual memory allocation is dangerous and you are prone to leaks. If you are not proficient at using the debugger or valgrind (a memory leak tool), you may pull your hair out of your head. Luckily RAII idioms and smart pointers alleviate this a bit, but you must be familiar with practices such as The Rule Of Three and The Rule Of Five. It is a lot of information to take in, and beginners who either don't know or don't care will fall into this trap.

  • It is not necessary. Unlike Java and C# where it is idiomatic to use the new keyword everywhere, in C++, you should only use it if you need to. The common phrase goes, everything looks like a nail if you have a hammer. Whereas beginners who start with C++ are scared of pointers and learn to use stack variables by habit, Java and C# programmers start by using pointers without understanding it! That is literally stepping off on the wrong foot. You must abandon everything you know because the syntax is one thing, learning the language is another.

1. (N)RVO - Aka, (Named) Return Value Optimization

One optimization many compilers make are things called elision and return value optimization. These things can obviate unnecessary copys which is useful for objects that are very large, such as a vector containing many elements. Normally the common practice is to use pointers to transfer ownership rather than copying the large objects to move them around. This has lead to the inception of move semantics and smart pointers.

If you are using pointers, (N)RVO does NOT occur. It is more beneficial and less error-prone to take advantage of (N)RVO rather than returning or passing pointers if you are worried about optimization. Error leaks can happen if the caller of a function is responsible for deleteing a dynamically allocated object and such. It can be difficult to track the ownership of an object if pointers are being passed around like a hot potato. Just use stack variables because it is simpler and better.

Yoon5oo
  • 489
  • 5
  • 11
user3391320
  • 943
  • 6
  • 8
  • "So !test is essentially a shorthand for checking if test is NULL or an invalid pointer, which means the cast failed." I think this sentence must be rewritten for clarity. – berkus Mar 14 '14 at 10:34
  • 4
    "The Java hype machine would like you to believe" -- maybe in 1997, but this is now anachronistic, there's no longer motivation to compare Java to C++ in 2014. – Matt R Mar 14 '14 at 13:52
  • 17
    Old question, but in the code segment ``{ std::string* s = new std::string; } delete s; // destructor called`` ....surely this ``delete`` won't work because the compiler won't know what ``s`` is anymore? – badger5000 Jun 29 '14 at 22:55
  • "...the distinction between pointers and arrays are hand-waved in Java..." Not at all. Setting aside that Java doesn't have pointers (it has nullable references), arrays are a type like any other. You can't "handwave" the reference by discarding array syntax and pretending it is a reference to its first element. `int[] nums = { 0 }; int zero = nums;` won't compile. – Justin Nov 05 '14 at 21:41
  • 2
    I am NOT giving -1, but I disagree with the opening statements as written. First, I disagree there is any "hype" - might have been around Y2K, but now both languages are well understood. Second, I would argue that they are quite similar - C++ is the child of C married with Simula, Java adds Virtual Machine, Garbage Collector and HEAVILY cuts down on features, and C# streamlines and reintroduces missing features to Java. Yes, this makes patterns and valid use HUGELY different, but it is beneficial to understand the common infrastructure/desing so that one can see the differences. – Gerasimos R Jan 19 '17 at 10:52
  • @Shoe: They're nullable references *with position*. A Java reference points to a thing that exists "somewhere", but not a specific place that you can relate to the position of other objects. A C++ pointer has position, and can be moved; if you have a C++ pointer to the 12th element of an array (stack or heap), you can increment or decrement it to move it to a neighbor, index it to look at a neighbor without mutating it, etc. You can compute the distance between two pointers and use it to operate at two paired offsets in an array. In Java, the references have no position. – ShadowRanger Jul 13 '17 at 02:28
  • I just wanted to chip in a few cents here. The answer states a couple times that the heap is slow. Usage of the heap is no faster or slower than the stack. **Allocation** from the heap *can be / is* slow (depending on the allocator behavior), same for deletion. And if you constantly allocate and delete objects you can also pay the cost of a virtual memory leak. To avoid those pitfalls simply: allocate early, delete late, reuse memory and objects as much as possible, memory pools are a common method for this. – James Matta Oct 17 '17 at 17:30
  • Arrays are not pointers: There is a big difference between casting something to (int *) or (int[]) – shjeff Jul 24 '18 at 09:23
  • 1
    @James Matta: You are of course correct that memory is memory, and they are both allocated from the same physical memory, but one thing to consider is that it is very common to get better performance characteristics working with stack allocated objects because the stack - or at least its highest levels - have a very high chance of being "hot" in cache as functions enter and exit, while the heap does not have such a benefit so if you are pointer chasing in the heap you *may* get multiple cache misses which you *likely* would not on the stack. But all this "randomness" normally favors the stack. – Gerasimos R Oct 30 '19 at 15:21
  • I found your write-up quite informative ... THanks +1 – JonoJames Mar 10 '21 at 21:59
80

Another good reason to use pointers would be for forward declarations. In a large enough project they can really speed up compile time.

Michael Petrotta
  • 56,954
  • 26
  • 136
  • 173
Burnt Toast
  • 909
  • 5
  • 2
  • 3
    std::shared_ptr also works with forward declarations of T. (std::unique_ptr **doesn't**) – berkus Mar 14 '14 at 10:23
  • 13
    @berkus: `std::unique_ptr` does work with forward declarations of `T`. You just need to make sure that when the destructor of the `std::unique_ptr` is called, `T` is a complete type. This typically means your class that contains the `std::unique_ptr` declares its destructor in the header file and implements it in the cpp file (even if the implementation is empty). – David Stone Nov 27 '14 at 16:25
  • Will modules fix this? – Trevor Hickey Nov 09 '15 at 15:55
  • @TrevorHickey Old comment I know, but to answer it anyways. Modules won't remove the dependency, but should make including the dependency very cheap, almost free in terms of performance cost. Also, if the general speedup from modules would be enough to get your compile times in an acceptable range, it's no longer an issue either. – Aidiakapi Oct 13 '17 at 18:08
  • Why would you want to speed up compile time for yourself at the expense of the end user? – Jack Giffin Dec 29 '17 at 19:20
23

In C++, objects allocated on the stack (using Object object; statement within a block) will only live within the scope they are declared in. When the block of code finishes execution, the object declared are destroyed. Whereas if you allocate memory on heap, using Object* obj = new Object(), they continue to live in heap until you call delete obj.

I would create an object on heap when I like to use the object not only in the block of code which declared/allocated it.

  • 6
    `Object obj` is not always on the stack - for example globals or member variables. – tenfour Mar 03 '14 at 12:03
  • 2
    @LightnessRacesinOrbit I mentioned only about the objects allocated in a block, not about global and member variables. Thing is it was not clear, now corrected it - added "within a block" in the answer. Hope its not false information now :) – Karthik Kalyanasundaram Mar 04 '14 at 09:51
23

C++ gives you three ways to pass an object: by pointer, by reference, and by value. Java limits you with the latter one (the only exception is primitive types like int, boolean etc). If you want to use C++ not just like a weird toy, then you'd better get to know the difference between these three ways.

Java pretends that there is no such problem as 'who and when should destroy this?'. The answer is: The Garbage Collector, Great and Awful. Nevertheless, it can't provide 100% protection against memory leaks (yes, java can leak memory). Actually, GC gives you a false sense of safety. The bigger your SUV, the longer your way to the evacuator.

C++ leaves you face-to-face with object's lifecycle management. Well, there are means to deal with that (smart pointers family, QObject in Qt and so on), but none of them can be used in 'fire and forget' manner like GC: you should always keep in mind memory handling. Not only should you care about destroying an object, you also have to avoid destroying the same object more than once.

Not scared yet? Ok: cyclic references - handle them yourself, human. And remember: kill each object precisely once, we C++ runtimes don't like those who mess with corpses, leave dead ones alone.

So, back to your question.

When you pass your object around by value, not by pointer or by reference, you copy the object (the whole object, whether it's a couple of bytes or a huge database dump - you're smart enough to care to avoid latter, aren't you?) every time you do '='. And to access the object's members, you use '.' (dot).

When you pass your object by pointer, you copy just a few bytes (4 on 32-bit systems, 8 on 64-bit ones), namely - the address of this object. And to show this to everyone, you use this fancy '->' operator when you access the members. Or you can use the combination of '*' and '.'.

When you use references, then you get the pointer that pretends to be a value. It's a pointer, but you access the members through '.'.

And, to blow your mind one more time: when you declare several variables separated by commas, then (watch the hands):

  • Type is given to everyone
  • Value/pointer/reference modifier is individual

Example:

struct MyStruct
{
    int* someIntPointer, someInt; //here comes the surprise
    MyStruct *somePointer;
    MyStruct &someReference;
};

MyStruct s1; //we allocated an object on stack, not in heap

s1.someInt = 1; //someInt is of type 'int', not 'int*' - value/pointer modifier is individual
s1.someIntPointer = &s1.someInt;
*s1.someIntPointer = 2; //now s1.someInt has value '2'
s1.somePointer = &s1;
s1.someReference = s1; //note there is no '&' operator: reference tries to look like value
s1.somePointer->someInt = 3; //now s1.someInt has value '3'
*(s1.somePointer).someInt = 3; //same as above line
*s1.somePointer->someIntPointer = 4; //now s1.someInt has value '4'

s1.someReference.someInt = 5; //now s1.someInt has value '5'
                              //although someReference is not value, it's members are accessed through '.'

MyStruct s2 = s1; //'NO WAY' the compiler will say. Go define your '=' operator and come back.

//OK, assume we have '=' defined in MyStruct

s2.someInt = 0; //s2.someInt == 0, but s1.someInt is still 5 - it's two completely different objects, not the references to the same one
Kirill Gamazkov
  • 2,948
  • 1
  • 15
  • 21
  • 1
    `std::auto_ptr` is deprecated, please don't use it. – Neil Mar 09 '14 at 19:53
  • 2
    Pretty sure you can't have a reference as a member without also providing a constructor with an initialization list that includes the reference variable. (A reference has to be initialized immediately. Even the constructor body is too late to set it, IIRC.) – cHao Jul 25 '14 at 19:32
20

But I can't figure out why should we use it like this?

I will compare how it works inside the function body if you use:

Object myObject;

Inside the function, your myObject will get destroyed once this function returns. So this is useful if you don't need your object outside your function. This object will be put on current thread stack.

If you write inside function body:

 Object *myObject = new Object;

then Object class instance pointed by myObject will not get destroyed once the function ends, and allocation is on the heap.

Now if you are Java programmer, then the second example is closer to how object allocation works under java. This line: Object *myObject = new Object; is equivalent to java: Object myObject = new Object();. The difference is that under java myObject will get garbage collected, while under c++ it will not get freed, you must somewhere explicitly call `delete myObject;' otherwise you will introduce memory leaks.

Since c++11 you can use safe ways of dynamic allocations: new Object, by storing values in shared_ptr/unique_ptr.

std::shared_ptr<std::string> safe_str = make_shared<std::string>("make_shared");

// since c++14
std::unique_ptr<std::string> safe_str = make_unique<std::string>("make_shared"); 

also, objects are very often stored in containers, like map-s or vector-s, they will automatically manage a lifetime of your objects.

Yoon5oo
  • 489
  • 5
  • 11
marcinj
  • 44,446
  • 9
  • 70
  • 91
  • 1
    `then myObject will not get destroyed once function ends` It absolutely will. – Lightness Races in Orbit Mar 03 '14 at 12:49
  • 6
    In the pointer case, `myObject` will still be destroyed, just as any other local variable will. The difference is that its value is a *pointer* to an object, not the object itself, and a dumb pointer's destruction doesn't affect its pointee. So the *object* will survive said destruction. – cHao Mar 03 '14 at 15:45
  • Fixed that, local variables (that includes pointer) of course will be freed - they are on stack. – marcinj Mar 03 '14 at 16:06
13

Technically it is a memory allocation issue, however here are two more practical aspects of this. It has to do with two things: 1) Scope, when you define an object without a pointer you will no longer be able to access it after the code block it is defined in, whereas if you define a pointer with "new" then you can access it from anywhere you have a pointer to this memory until you call "delete" on the same pointer. 2) If you want to pass arguments to a function you want to pass a pointer or a reference in order to be more efficient. When you pass an Object then the object is copied, if this is an object that uses a lot of memory this might be CPU consuming (e.g. you copy a vector full of data). When you pass a pointer all you pass is one int (depending of implementation but most of them are one int).

Other than that you need to understand that "new" allocates memory on the heap that needs to be freed at some point. When you don't have to use "new" I suggest you use a regular object definition "on the stack".

in need of help
  • 1,475
  • 12
  • 26
5

Let's say that you have class A that contain class B When you want to call some function of class B outside class A you will simply obtain a pointer to this class and you can do whatever you want and it will also change context of class B in your class A

But be careful with dynamic object

Quest
  • 2,568
  • 1
  • 17
  • 36
5

There are many benefits of using pointers to object -

  1. Efficiency (as you already pointed out). Passing objects to functions mean creating new copies of object.
  2. Working with objects from third party libraries. If your object belongs to a third party code and the authors intend the usage of their objects through pointers only (no copy constructors etc) the only way you can pass around this object is using pointers. Passing by value may cause issues. (Deep copy / shallow copy issues).
  3. if the object owns a resource and you want that the ownership should not be sahred with other objects.
Rohit
  • 341
  • 4
  • 16
5

Well the main question is Why should I use a pointer rather than the object itself? And my answer, you should (almost) never use pointer instead of object, because C++ has references, it is safer then pointers and guarantees the same performance as pointers.

Another thing you mentioned in your question:

Object *myObject = new Object;

How does it work? It creates pointer of Object type, allocates memory to fit one object and calls default constructor, sounds good, right? But actually it isn't so good, if you dynamically allocated memory (used keyword new), you also have to free memory manually, that means in code you should have:

delete myObject;

This calls destructor and frees memory, looks easy, however in big projects may be difficult to detect if one thread freed memory or not, but for that purpose you can try shared pointers, these slightly decreases performance, but it is much easier to work with them.


And now some introduction is over and go back to question.

You can use pointers instead of objects to get better performance while transferring data between function.

Take a look, you have std::string (it is also object) and it contains really much data, for example big XML, now you need to parse it, but for that you have function void foo(...) which can be declarated in different ways:

  1. void foo(std::string xml); In this case you will copy all data from your variable to function stack, it takes some time, so your performance will be low.
  2. void foo(std::string* xml); In this case you will pass pointer to object, same speed as passing size_t variable, however this declaration has error prone, because you can pass NULL pointer or invalid pointer. Pointers usually used in C because it doesn't have references.
  3. void foo(std::string& xml); Here you pass reference, basically it is the same as passing pointer, but compiler does some stuff and you cannot pass invalid reference (actually it is possible to create situation with invalid reference, but it is tricking compiler).
  4. void foo(const std::string* xml); Here is the same as second, just pointer value cannot be changed.
  5. void foo(const std::string& xml); Here is the same as third, but object value cannot be changed.

What more I want to mention, you can use these 5 ways to pass data no matter which allocation way you have chosen (with new or regular).


Another thing to mention, when you create object in regular way, you allocate memory in stack, but while you create it with new you allocate heap. It is much faster to allocate stack, but it is kind a small for really big arrays of data, so if you need big object you should use heap, because you may get stack overflow, but usually this issue is solved using STL containers and remember std::string is also container, some guys forgot it :)

ST3
  • 8,050
  • 2
  • 62
  • 85
4

This is has been discussed at length, but in Java everything is a pointer. It makes no distinction between stack and heap allocations (all objects are allocated on the heap), so you don't realize you're using pointers. In C++, you can mix the two, depending on your memory requirements. Performance and memory usage is more deterministic in C++ (duh).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
cmollis
  • 137
  • 3
3
Object *myObject = new Object;

Doing this will create a reference to an Object (on the heap) which has to be deleted explicitly to avoid memory leak.

Object myObject;

Doing this will create an object(myObject) of the automatic type (on the stack) that will be automatically deleted when the object(myObject) goes out of scope.

Palak Jain
  • 241
  • 2
  • 10
2

A pointer directly references the memory location of an object. Java has nothing like this. Java has references that reference the location of object through hash tables. You cannot do anything like pointer arithmetic in Java with these references.

To answer your question, it's just your preference. I prefer using the Java-like syntax.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Cozmo
  • 53
  • 3
  • Hash tables? Maybe in some JVMs but don't count on it. – Zan Lynx Mar 05 '14 at 22:21
  • What about the JVM that comes with Java? Of course you can implement ANYTHING you can think of like a JVM that uses pointers directly or a method that does pointer math. That's like saying "people don't die of the common cold" and getting a response "Maybe most people don't but don't count on it!" Ha ha. – Cozmo Mar 25 '15 at 16:49
  • 2
    @RioRicoRick HotSpot implements Java references as native pointers, see https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html As far as I can see, JRockit does the same. They both support OOP compression, but neither ever use hash-tables. The performance consequences would probably be disastrous. Also, "it's just your preference" seems to imply that the two are merely different syntaxes for equivalent behaviour, which of course they are not. – Max Barraclough Apr 11 '18 at 14:21
  • https://stackoverflow.com/questions/1750106/how-can-i-use-pointers-in-java – Cozmo Apr 16 '18 at 04:43
0

With pointers ,

  • can directly talk to the memory.

  • can prevent lot of memory leaks of a program by manipulating pointers.

lasan
  • 193
  • 13
0

One reason for using pointers is to interface with C functions. Another reason is to save memory; for example: instead of passing an object which contains a lot of data and has a processor-intensive copy-constructor to a function, just pass a pointer to the object, saving memory and speed especially if you're in a loop, however a reference would be better in that case, unless you're using an C-style array.

0

In areas where memory utilization is at its premium , pointers comes handy. For example consider a minimax algorithm, where thousands of nodes will be generated using recursive routine, and later use them to evaluate the next best move in game, ability to deallocate or reset (as in smart pointers) significantly reduces memory consumption. Whereas the non-pointer variable continues to occupy space till it's recursive call returns a value.

seccpur
  • 4,680
  • 2
  • 9
  • 17
0

I will include one important use case of pointer. When you are storing some object in the base class, but it could be polymorphic.

Class Base1 {
};

Class Derived1 : public Base1 {
};


Class Base2 {
  Base *bObj;
  virtual void createMemerObects() = 0;
};

Class Derived2 {
  virtual void createMemerObects() {
    bObj = new Derived1();
  }
};

So in this case you can't declare bObj as an direct object, you have to have pointer.

user18853
  • 2,281
  • 1
  • 17
  • 16
0

The key strength of object pointers in C++ is allowing for polymorphic arrays and maps of pointers of the same superclass. It allows, for example, to put parakeets, chickens, robins, ostriches, etc. in an array of Bird.

Additionally, dynamically allocated objects are more flexible, and can use HEAP memory whereas a locally allocated object will use the STACK memory unless it is static. Having large objects on the stack, especially when using recursion, will undoubtedly lead to stack overflow.

-4

"Necessity is the mother of invention." The most of important difference that I would like to point out is the outcome of my own experience of coding. Sometimes you need to pass objects to functions. In that case, if your object is of a very big class then passing it as an object will copy its state (which you might not want ..AND CAN BE BIG OVERHEAD) thus resulting in an overhead of copying object .while pointer is fixed 4-byte size (assuming 32 bit). Other reasons are already mentioned above...

Yoon5oo
  • 489
  • 5
  • 11
sandeep bisht
  • 105
  • 12
  • 14
    you should prefer passing by reference – bolov Mar 06 '14 at 08:20
  • 2
    I recommend passing by constant-reference like for variable `std::string test;` we have `void func(const std::string &) {}` but unless the function needs to change the input in which case I recommend using pointers (so that anyone reading the code does notice `&`, and understands the function may change its input) – Top-Master Dec 16 '18 at 09:42
-7

There are many excellent answers already, but let me give you one example:

I have an simple Item class:

 class Item
    {
    public: 
      std::string name;
      int weight;
      int price;
    };

I make a vector to hold a bunch of them.

std::vector<Item> inventory;

I create one million Item objects, and push them back onto the vector. I sort the vector by name, and then do a simple iterative binary search for a particular item name. I test the program, and it takes over 8 minutes to finish executing. Then I change my inventory vector like so:

std::vector<Item *> inventory;

...and create my million Item objects via new. The ONLY changes I make to my code are to use the pointers to Items, excepting a loop I add for memory cleanup at the end. That program runs in under 40 seconds, or better than a 10x speed increase. EDIT: The code is at http://pastebin.com/DK24SPeW With compiler optimizations it shows only a 3.4x increase on the machine I just tested it on, which is still considerable.

Darren
  • 237
  • 1
  • 9
  • 2
    Well are you comparing the pointers then or do you still compare the actual objects? I very much doubt that another level of indirection can improve performance. Please provide code! Do you properly clean up afterwards? – stefan Feb 05 '15 at 18:38
  • 1
    @stefan I compare the data (specifically, the name field) of the objects for both the sort and the search. I clean up properly, as I mentioned already in the post. the speedup is probably due to two factors: 1) std::vector push_back() copies the objects, so the pointer version only need copy a single pointer per object. This has multiple impacts on the performance, as not only is less data copied, but the vector class memory allocator gets thrashed less. – Darren Feb 05 '15 at 21:48
  • 2) The sort just has to exchange pointers, not entire objects (I just used the std::sort algorithm with a simple string comparison in both cases, adapted to dereference the pointers in the second case). Again, I emphasize: "The ONLY changes I make to my code are to use the pointers to Items, excepting a loop I add for memory cleanup at the end." – Darren Feb 05 '15 at 21:49
  • The code is at work, but you could try it yourself. I used VS2013 and all default options. I think it highly rude and ignorant to downvote me because you don't understand that copying and moving pointers is faster than copying and moving entire objects. – Darren Feb 05 '15 at 21:55
  • While this operation (sorting) may be faster, other's will suffer from the indirection massively. See e.g. http://ideone.com/k7CFWK This is a 20x pessimization (3.4x for just the sum). I don't say that this example is representative for most code, but it isn't _per se_ a good idea to introduce pointers. – stefan Feb 05 '15 at 22:17
  • 2
    Here's code showing practically no difference for your example: sorting. The pointer code is 6% faster than the non-pointer code for the sort alone, but overall it's 10% slower than the non-pointer code. http://ideone.com/G0c7zw – stefan Feb 05 '15 at 22:31
  • 3
    Key word: `push_back`. Of course this copies. You should have been `emplace`ing in-place when creating your objects (unless you need them to be cached elsewhere). – underscore_d Jul 14 '15 at 19:05
  • 1
    Vectors of pointers are almost always wrong. Please don't recommend them without explaining, in detail, the caveats and the pros and cons. You seem to have found one pro, which is only a consequence of a poorly coded counter-example, and misrepresented it – Lightness Races in Orbit Jan 20 '19 at 17:45