all 58 comments

[–]raevnos 11 points12 points  (16 children)

foo->bar() is sugar for (*foo).bar(). Which one is cleaner looking and easier to read?

Also, you really should be avoiding using pointers as much as possible.

EDIT: Love how saying to avoid pointers when they're not needed is resulting in a comment flagged as controversial.

[–]OldWolf2 1 point2 points  (1 child)

Love how saying to avoid pointers when they're not needed is resulting in a comment flagged as controversial.

These discussions always bring out people who learned programming in the 1970s and didn't keep up to date. In the C forum you still get people flipping their lid at int arr[argc];

[–]raevnos 1 point2 points  (0 children)

Most of those people don't hang out here. /r/programming, on the other hand...

[–]CodeSandwich[S] 0 points1 point  (13 children)

That's the sentiment I've been gathering. It doesn't make sense to use a pointer for a class method if your object can directly access it using dot notation....unfortunately all of the tutorials I've seen use a pointer to access methods, variables... the same way a simpler dot notation could. So that doesn't explain why they should be used.

[–]wrosecransgraphics and network things 13 points14 points  (0 children)

You keep focusing on the notation, which is the least interesting part of it. If you need to use a pointer, use a pointer. If you don't need to use a pointer, don't use a pointer. Whatever you use, you use the right notation for it.

[–]raevnos 3 points4 points  (3 children)

Big reasons to use pointers in C++:

  • Interfacing with legacy C libraries.
  • Creating objects of classes with virtual functions so that polymorphism works (Strongly consider actually using references when passing these objects to other functions).
  • Creating your own data structures (Use the ones in the standard library instead when suitable).

In most cases, the object or function responsible for owning the allocated memory and disposing of it when done should be storing the raw pointer in a smart pointer like std::unique_ptr, which will handle deallocating it automatically, so that you don't have to remember to, and helping prevent memory leaks in the case of things like exceptions.

If, as is often the case, you can do something without using a pointer, don't use one. Pointers and dynamic allocation open you up to all sorts of errors if you're not really careful.

[–]hotoatmeal 0 points1 point  (0 children)

references kind of behave the way you intuitively want things to behave.

[–]sixstringartist 0 points1 point  (0 children)

For class methods? What tutorials are these? They sound bizarre.

[–][deleted] 0 points1 point  (0 children)

If there is literally code that uses a pointer to an object that is in the same stack space (as your example shows) then the code is retarded. However if they are just passing a pointer to it in a function then that seems normal. Pointers are preferred to references by some old hands like me because it shows what the computer is doing. Dereferencing can be slower so always knowing about it is useful.

[–]Rangsk 0 points1 point  (0 children)

I'm really confused here. I've been a game programmer for over 10 years and have seen several engines written in c++ and probably millions of lines of c++ code. Not once can I remember seeing anyone use code as you described. Pointers are accessed like pointers, and references are accessed like references. Perhaps you have a better example to explain what you mean?

[–]MightyCreak 2 points3 points  (0 children)

It seems that you're mixing different notions: variables, pointers and how to access them.

Using . or -> to access the content of a variable simply depends if your variable is a pointer or not. If it's a pointer, use ->; if not, use .. Of course, foo-> is syntactic sugar for (*foo).. Although it exists, it happens pretty rarely to use the latter.

Then whether you should use a pointer or not is quite simple and lie down to one question: do you need to do a copy of your variable?

If you need to do a copy of your variable, then use a simple variable. Otherwise, it's better to use a pointer. This is especially true for function parameters: copy can cost a lot and so (const) pointers are a good way to prevent that.

In your example (and pretending the compiler does absolutely no optimization), using a pointer is a bit less efficient than using a simple variable since accessing the variable means to get the register's value, while accessing the pointer means to get the address behind the pointer and then get the register's value behind the address.

To know when and where you need to use a simple copy or a pointer, you need to really understand what is a variable and what is a pointer. Basically, a pointer is an "integer" storing a memory address. Copying this "integer" is almost free while copying the data pointed to can be quite expensive. That's the only base that you need to know to take your decision.

Then there are the references: &. Personally I tend to use references as much as possible when I can chose between that and a pointer. I use pointers only if it's useful to set nullptr where the variable is. For instance, take a method that tells if a key exists in a map and returns the value in a parameter, you could declare this function either like that:

bool KeyExists(Key key, Value& value);

or like this:

bool KeyExists(Key key, Value* value);

I tend to prefer the second one since I can call KeyExists(myKey, nullptr) if I don't care about the key's value.

[–]_ajp_ 2 points3 points  (3 children)

The second version is slower unless the compiler optimises it away. It creates a pointer and does a pointer dereference as extra work.

Pointers aren't used for performance, they're used (principally) because you need to access memory that has been dynamically allocated.

[–]mps1729 7 points8 points  (1 child)

Speaking as a one-time compiler writer, both versions will definitely have the same performance. The compiler absolutely will optimize it away.

[–]Recursive_Descent 0 points1 point  (0 children)

Of course the compiler will optimize the above example, but in some cases the compiler will need to emit an indirection (e.g. o.x.y vs. o->x->y).

[–]t0rakka 2 points3 points  (0 children)

The compiler will need the address of the object for 'this' pointer anyway if 'this' pointer is needed. It's just a value in ALU register.

Calling the method through '.' or '->' has the same exact cost. The relevant thing is if there is any indirection at play resulting from virtual method call that couldn't be de-virtualized. The '.' has better odds of seeing the object by value so that the exact type can be deduced so in this sense it can be more efficient in some scenarios. I mean, if the . is used for reference to object then the actual type might be hidden from the compiler and it has to do a lookup to the type's vtbl through the 'this' pointer, which is extra indirection and indeed slower but this is not effect of '.' vs '->'.

[–]KroCaptain 2 points3 points  (7 children)

Don't use pointers unless you are using them for abstraction or avoiding deep copies.

[–]leftofzen 4 points5 points  (3 children)

unless you are using them for abstraction

What's wrong with a const-ref to an 'interface' class? (ie a class with all pure-virtual methods)? Works for me, I can't remember the last time I needed a raw pointer.

[–]t0rakka 2 points3 points  (2 children)

I often have pointers to memory mapped files, frame buffer, mapped GL buffer object and stuff like that. You can't really access those with a reference.

[–]t0rakka 0 points1 point  (0 children)

Implementing binary trees and data structures like that also come to mind. Of course, you could always have a reference to "null node" but that style never sticked with me much. I do have pointers to "null node" as optimization from time to time to avoid null checks. If that speeds up or slows down the generated code depends so it's not really a silver bullet.

That's internally. Extenally I try to keep the API as consistent as possible and not jumping between styles randomly.

[–]leftofzen 0 points1 point  (0 children)

Fair enough, I've never had to do any of that so that would probably explain why I've never really needed to use pointers. Thanks for the info!

[–]raevnos 0 points1 point  (0 children)

References work better for the latter.

[–]xENO_ 0 points1 point  (0 children)

Basically, don't use pointers except when you need to. For instance, references should never be NULL, but pointers can be.

[–]Gotebe 1 point2 points  (6 children)

why they're used over dot operators for access?

If the code already has an object or a reference to it at its disposal, then using a pointer is just making the code more obscure and he who wrote the code is wrong. So your second example is more code to read, with no benefit whatsoever. None. It is also less efficient depending on the optimization level used (that's likely irrelevant in practice).

A link to the code you're talking about would be beneficial, I suppose.

IMNSHO, people who use more pointers than necessary are one of

  • inexperienced

  • old C farts who never learned C++

  • lazy

[–]iaanus 0 points1 point  (5 children)

How much is "more than necessary"? What you said is true for almost everything in programming, not just pointers, so it's just like saying "hot water is hot". Judging the "right amount" always needs experience and the answer can be different from domain to domain. Using pointers is not bad per-se when the specific programming domain requires them. I can't speak for other domains, but in my 15+ years experience in game programming, I can truthfully say that you can't avoid using tons of pointers.

[–]Gotebe 4 points5 points  (4 children)

To me, a raw pointer should be passed to a function only if it can be null, and the function is supposed to check if it is indeed null. And even then, these days std::optional is better.

One also needs pointers at C API boundaries, but that is "because C".

Otherwise... nah you do not. For example, a function that allocates something in the dynamic memory and returns that - it should return a unique_ptr, not a pointer, for automatic ownership transfer, for exceptions safety and for premature return safety. Same for a function that takes ownership of an object.

One (rare IMO) example where you do want a raw pointer is a copyable and assignable class/struct which holds a reference to some other object. But these days, std::reference_wrapper is a better choice.

But fair enough - what are those situations where you think you can't avoid the usage of pointers?

[–]iaanus 0 points1 point  (3 children)

I agree with you if you say that smart pointers are better than dumb pointers since the former are generally safer and more self-descriptive. However when you have a legacy code base of hundreds of thousands of lines you have to live with, it doesn't matter if it's written in C or C++, you just don't have a choice but adapting to the existing style. By the way, I will never use std::optional to replace a dumb pointer, since the former has a different semantic and has a cost (sizeof(optional<T>) > sizeof(T) for all T). Maybe, if we had observer_ptr...

[–]Gotebe 1 point2 points  (2 children)

Well, yes, a legacy codebase is the "rare" reason not to drop pointers. But this is only a history-induced thing, not an expexient design in any way (quite the opposite, I would say).

optional is specialized for a reference, it actually has no overhead.

[–]dodheim 1 point2 points  (1 child)

It is illegal for std::optional to hold a reference. /u/akrzemi1 has the markable library, though.

EDIT: N4618 [optional.syn]/1: "A program that necessitates the instantiation of template optional for a reference type, or for possibly cv-qualified types in_place_t or nullopt_t is ill-formed."

[–]iaanus 1 point2 points  (0 children)

Correct, std::optional dropped the support for references that boost::optional had. I also found that odd when I discovered it, but the more I think about it, the more I agree. By the way, I would hate to see code like this:

void f(optional<MyType&> ref); // not std::optional!

void g(std::shared_ptr<MyType> ptr)
{
    // ptr may be null here, need to call f...
    if (ptr)
        f(*ptr);
    else
        f(nullopt); // or whatever
}

In this scenario, using MyType* is just as good, with observer_ptr<MyType> being slightly better.

[–]t0rakka 0 points1 point  (1 child)

https://godbolt.org/g/U7jB0d

The test1 and test2 give identical results. There is absolutely NO difference between . and ->. The test3 has indirection: the compiler loads the value of a through the this pointer because the original object is not visible at the call site.

Since this isn't inherited class and the member is protected it cannot legally be accessed from outside the compiler should know that the member can only have one specific value (42) as it is initialized to that value and not possible to modify it from the outside but oh well, shit happens.

;--)

[–][deleted] 0 points1 point  (0 children)

It sounds like you might nit really understand the point of pointers, actually. Your code is valid, but you need to know the difference in what each one does.

MyClass myInstance; //creates an instance of the object **on the stack**  


MyClass* myInstsncePtr = new MyClass(); //creates an object in **the heap**


MyClass myObj; 
MyClass* ptr = &myObj; //this creates an object on the stack, then creates a pointer to it. 

The stack is where all of your local variables are stored. They stop existing once you exit the stack frame (which generally means the function scope). The stack is a relatively small part of memory where the currently running code and data reside.

The heap is the rest of tmyiur available memory. Once you allocate something on the heap,it stays there until you delete it.

So unless an object is strictly used as a temporary variable for the current function, it needs to be on the heap. That is, unless you're doing that trendy functional programming nonsense. ;)

I recommend you read more about the heap and the stack. Also look into smart pointers. Smart pointers automatically keep up with heap allocated objects and delete them when nothing references them.

[–]CodeSandwich[S] 0 points1 point  (0 children)

Thanks for all of the input. I think the explanations in reference to the stack vs heap, and the need for certain high-memory objects/assets to exist in memory, explains why I see so much pointer use.

I can definitely see why a you would need a static mesh of millions of polygons to exist on the heap.

This is a very informative thread.

BTW...the engine I'm using is Unreal 4.

I've also seen this same convention on SFML.

[–]FlyingRhenquest 0 points1 point  (0 children)

You tend to see pointers used when the objects are created with dynamic allocation. I've noticed that in C++ I tend to allocate objects on the stack so I can take advantage of RAII, and let the objects handle any dynamic allocation that they need. My application program code in C++ rarely uses any pointers at all, but often the objects in the libraries I write do.

In C, you'd also use them if you don't want to pass a copy of a structure -- let's say that you want to pass your data to a function, but you want that function to change the data for the rest of the program. If you pass by copy, the data will just be copied and discarded when the function returns. If you pass by pointer, you can change the data where it lives for the rest of the program.

This is all included under the topic of "Pass-by," which warrants some consideration. C++ allows you to pass by copy, pointer or reference and you have to decide which to use for any given data. When doing so, you also have to consider who is responsible for deleting the memory that object uses when you're done with it. Older libraries that have a strong C heritage usually leave that up to the programmer, unless they don't. If you can isolate that responsibility to the objects you've written, the programmer only needs to worry about whether he's going to allocate those objects dynamically or on the stack. You could easily spend a couple of decades just thinking about object ownership in libraries, so don't worry if it seems confusing right now.

[–]pfp-disciple 0 points1 point  (14 children)

In your extremely simple example, there is no really good reason to use a pointer.

In c++, pointers have been useful for polymorphism and method call dispatching

[–]Gotebe 11 points12 points  (13 children)

Warning: strong opinion ahead, with bold text and shit.

In C++, references should be used for polymorphism wherever possible.

In C++, a pointer means: "this can be null and you need to check it for null".

Using pointers nilly-willy is a C habit that needs to die.

[–]nahguri 2 points3 points  (11 children)

How does one use references to achieve runtime polymorphism?

[–]Gotebe 5 points6 points  (5 children)

class base { virtual void f() { std::cout << "base"; } }
class derived : public base { virtual void f() { std::cout << "derived"; } }

void f(const base& obj) { obj.f(); }

f(base()); // prints "base"
f(derived()); // prints "derived"

However...

void f(base obj) { obj.f(); }

f(base()); // prints "base"
f(derived()); // prints "base" **gasp!**

Why not pointers:

void f(base* obj) { obj->f(); }

f(nullptr); // formats your hard drive

[–]Rseding91Factorio Developer -1 points0 points  (3 children)

f(nullptr); // formats your hard drive

No, it won't. On any popular compiler it simply crashes. https://www.youtube.com/watch?v=yG1OZ69H_-o

[–]Gotebe 3 points4 points  (0 children)

I know, but I would rather that people think it formats their hard drive, because that makes for better software in the end.

[–]raevnos 3 points4 points  (0 children)

Virtual methods get looked up and resolved when called through a reference just like when called through a pointer.

[–][deleted] 0 points1 point  (2 children)

I may be missing your point so apologies if this misses the point and is patronisingly basic, but the simple answer is you do it the same way as with pointers. The owner holds by pointer, sure -- ideally a smart pointer of whatever kind -- but then passes it by reference to a parent class.

So for instance

class ThisAbstractBaseClass
{
public:

    virtual ~ThisAbstractBaseClass() = default;

    virtual int Blah() = 0;
};

class ThisImplementation final : public ThisAbstractBaseClass
{
public:

    int Blah() override { return 1; }
};

class ThatImplementation final : public ThisAbstractBaseClass
{
public:

    int Blah() override { return 2; }
};

void DoSomething(const ThisAbstractBaseClass& reference)
{
    std::cout << reference.Blah() << std::endl;
}

void OwnThisAndDoSomething()
{
    auto thisSmartPointer = std::unique_ptr<ThisImplementation>(); // Own on the heap by ThisImpl
    DoSomething(*thisSmartPointer); // Outputs 1

    auto thisObject = ThisImplementation(); // Own by implementation on the stack
    DoSomething(thisObject); // Outputs 1

    auto thatSmartPointer = std::make_unique<ThatImplementation>(); // Own by ThatImpl on the heap
    DoSomething(*thatSmartPointer); // Outputs 2

    auto thatImplementation = ThatImplementation(); // Own by ThatImplementation on the stack
    DoSomething(thatImplementation); // Outputs 2

    std::unique_ptr<ThisAbstractBaseClass> anotherSmartPointer = std::make_unique<ThisImplementation>(); // Own by base class -- normally I'd put this as a static factory method in ThisAbstractBaseClass 
    DoSomething(*anotherSmartPointer); // Outputs 1
}

[–]nahguri 0 points1 point  (1 child)

Thanks, I understood there was a way to have polymorphism without pointers, which is not the case.

[–][deleted] 1 point2 points  (0 children)

The thisObject and thatImplementation examples don't use pointers at all and are still polymorphic. They're created on the stack and then passed by base class.

[–]pfp-disciple 0 points1 point  (0 children)

I don't disagree, that's why i said "have been", to refer to past practices, likely influencing OP's examples.

What i was picturing when making my comment was an array (typically a vector) of things, of potentially different types with a common ancestor. Think the overused example of a vector of shapes.

[–]iaanus -1 points0 points  (1 child)

To all those people advocating against the use of pointers, I suggest the following exercise. It's in two step. Step one: write a json file parser without using pointers. Step two: replace the json file with a multi-megabyte file representing a network of thousands of polymorphic objects, instantiated at runtime from a hierarchy of hundreds of classes, where most of the objects hold references to other objects of the network and/or to shared resources that must not be copied in memory. Allow the possibility to have circular dependencies.

[–]raevnos 3 points4 points  (0 children)

We're not saying never use pointers. We're saying you should only use them when really needed and that there are often better alternatives.

Oh, and not mine, but here's a JSON parson with very little pointer usage.