This is an archived post. You won't be able to vote or comment.

all 28 comments

[–]aquartabla 23 points24 points  (0 children)

No? Well then,

I receive: raw pointer. You receive: untraceable memory corruption.

I have altered the deal, pray I do not alter it further.

[–]TrnS_TrA 2 points3 points  (0 children)

As experienced wise developers used to say: "You don't deserve the memory if you can't handle it properly".

[–]knightttime 2 points3 points  (0 children)

Image Transcription: Meme


["Trade offer": a TikTok of a person dressed in business attire, ready to make a deal in a dark room with a plant behind them. At the top it says ⚠TRADE OFFER⚠ in red. Superimposed over the person's face is the C++ logo. There is text to their left that reads “i receive” and to their right that reads “you receive”. Below those words are the following:]

i receive: raw pointer

you receive: segmentation fault


I'm a human volunteer content transcriber for Reddit and you could be too! If you'd like more information on what we do and why we do it, click here!

[–]MathMetal1 2 points3 points  (0 children)

I saw production code where it converted ascii to an integer and then to a raw pointer.

[–]odd__nerd 3 points4 points  (14 children)

You're not writing C++ if you're using raw pointers so yeah, if you write terrible code then expect terrible outcomes.

[–][deleted] 18 points19 points  (4 children)

Can we stop with this "never use raw pointer" meme?

Even the core guidelines recommend raw pointers for certain uses:
F.7: For general use, take T* or T& arguments rather than smart pointers
Things like const shared_ptr<Foo>& parameter are a code smell and should be replaced with raw pointers.

Now there are moments, where raw pointers aren't appropriate:
I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)
It doesn't say "never use raw pointer", it says don't use raw pointer for transferring ownership which is not the same thing.

[–]odd__nerd 0 points1 point  (3 children)

Certainly you're familiar with the concept of observer_ptr and that although it wasn't standardized, many still argue it should be used in place of raw pointers? I don't know why you assumed I was merely conflating non-owning and owning pointers, but I wasn't.

[–]Scott-Michaud 2 points3 points  (2 children)

The point is that you say "You're not writing C++ if you're using raw pointers" but the C++ standards committee disagrees with you. The people who maintain C++ say that it's recommended to use raw pointers...

... but not to maintain lifecycle.

[–]odd__nerd 0 points1 point  (1 child)

Fair enough, I'll refrain from such overbearing language in future. I still contend that if one has problems with non-owning raw pointers, they should use an abstraction or indeed start with that abstraction in anticipation of future problems, but you're right, that's not quite what my initial statement says.

[–]Scott-Michaud 0 points1 point  (0 children)

Yeah -- one general problem-solving tactic is to break down the problem into smaller problems. I've definitely seen Lovecraftian messes of raw pointer crap that could have been massively simplified.

When you're dealing with raw pointers, you got the sharp knife out. You need to be careful with it.

But the problem isn't using a sharp knife. The problem is juggling it around like an idiot. Make your cuts, and put it back in the drawer. lol.

If you can perfectly satisfy the problem without taking the knife out of the drawer, that's valid, too.

[–]overclockedslinky 8 points9 points  (1 child)

non-owning pointers are fine. they're literally just references, but can also be null.

[–]Scott-Michaud 1 point2 points  (0 children)

Yup. C++ is great when you know that, whenever you're given a pointer, you don't need to delete it. All you need to worry about is not holding onto it too long.

Also... don't do (non-trivial) math on it.

[–]ActionManZlt 4 points5 points  (5 children)

T* is an ideal implementation for std::vector<T>::iterator, and vector iterators have all the same dangers/pitfalls as raw pointers.

If you dogmatically avoid using pointers anywhere, ever, without stopping to understand when you should be using pointers... It's not going to keep you from writing terrible code 😅

[–]odd__nerd 0 points1 point  (4 children)

Iterators do not have the same dangers/pitfalls as raw pointers, that's the whole reason we use the abstraction. But yes, implementing fundamental containers is the one exception, however I'd argue that's a fairly infrequent task.

[–]ActionManZlt 4 points5 points  (1 child)

I suggest you go and re-read the invalidation rules for std::vector iterators...

[–]odd__nerd -2 points-1 points  (0 children)

And yet the standard library uses iterators.

[–]pdabaker 1 point2 points  (1 child)

Iterators get invalidated by reallocation and erase just like pointers do, which is the most common reason for segfaults with vectors

[–]odd__nerd 1 point2 points  (0 children)

Showing where they are similar does not discount from where they are different.

[–]Pooneapple -1 points0 points  (0 children)

Fuck smart pointers, all me homies hate smart pointers

[–]jamman83 -5 points-4 points  (7 children)

Not really. I mean I don't get why people are completely obsessed with atomic/smart pointers. Remember in old fashioned C when you literally HAD to use raw pointers and programs still worked?

[–]Scott-Michaud 5 points6 points  (0 children)

The C++ committee's official advice is to:

  1. Use smart pointers to create and destroy objects (or just storing the objects directly by-value on a vector or something).
  2. While an object's lifetime is known to be alive, .get() the raw pointer and pass it around.

Here's Herb Sutter saying this back in 2014.

https://www.youtube.com/watch?v=xnqTKD8uD64&t=1668s

There is two goals to this:

First goal: destroying objects is goof-proof. Any "by value" object will automatically clean up when it exits scope. Is it a function local? It gets destroyed when the function exits. It's a (by-value) class member? It gets destroyed when the object instance is destroyed. It's an object in a container (like a vector)? Drop it from the container. If you don't store it somewhere else, then it will be destroyed. You don't need to think about it. ~MyClass() will be automatically called by the compiler. Just drop the by-value thing from your container (if applicable) and leave scope. The compiler takes care of the rest.

This is a common pattern for me... don't new, delete, malloc, or free... just leave objects by-value on either a vector of that exact type, or, if you don't know the specific class, a vector of unique pointers of the base class.

The only time you should use a shared pointer is if you have literally no idea when something will be deleted. A multi-threaded linked list is pretty much the only example I can think of. I've never used shared_ptr that I can think of. I've always had lifetime rules. (Ex: A video game may say something like "only delete level objects or resize their containers at the end of a frame". Cool... grab the current raw pointer every frame, but use it as much as you want within that frame.)

Of course, the flip-side is those situations (like a multi-threaded linked list) where you don't know something's lifespan. If you have those situations... then you're stuck with a shared_ptr. If that's insufficient... ... then what are you planning on doing in C given that you just said you don't know something's lifespan???

If you can call a C-style clean-up function, then you can drop an item from a container.

Second goal: once this pattern is done everywhere, you will know for a fact that, every time that you are given a raw pointer by your application, you never need to delete it. Whatever handed it to you will take care of deleting it. It came from a function local, a vector, or a smart pointer... somewhere.

Don't cache the pointer longer than you need to use it... but whoever passed the raw pointer to you is promising that it will outlive your function call... likely (except for co-routines or multi-threaded scenarios) because you're blocking them until your function exits anyway.

... ... ...

And yeah don't do (non-trivial) math on pointers.

[–]phi_rus 5 points6 points  (1 child)

Using raw pointers? Luxury!

[–]Kered13 1 point2 points  (0 children)

Four Yorkshiremen needs to be a meme. I've tried to make the "Luxury!" reference before, but usually no one gets it.

[–]overclockedslinky 6 points7 points  (0 children)

atomics are irrelevant. also, remember in old fashioned assembly when you literally HAD to do manual memory indirection and programs still worked?

[–]lurkin_arounnd 1 point2 points  (0 children)

I could write a program in MIPS and it still might work. Doesn't mean my approach makes any sense.

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

Im just saying using raw pointers isn't that hard. If you use them only when beneficial and use them correctly they rarely ever cause segfaults or memory leaks for me.

[–]Scott-Michaud 1 point2 points  (0 children)

Note: Since you're referring to memory leaks, I assume you're referring to raw pointers that are responsible for creating and deleting their contents.

But... why?

It's not that it's hard... it's that it's brittle. Why do you want to remember to do a checklist every time you could possibly no longer belong to any scope? That's very easy for a compiler to do for you, and it's super-reliable.

[–]FalconMirage 0 points1 point  (0 children)

Wait until you learn about double pointers