frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

Google, DOJ tussle over how AI will remake the web in antitrust closing argument

https://arstechnica.com/gadgets/2025/05/google-and-doj-tussle-over-how-ai-will-remake-the-web-in-antitrust-closing-arguments/
1•rntn•1m ago•0 comments

Apple Savings cuts its interest rate again, this time to 3.65%

https://appleinsider.com/articles/25/05/28/apple-savings-cuts-its-interest-rate-again-this-time-to-365
1•behnamoh•1m ago•0 comments

What if, the scouter from Dragon ball, or aiming HUD from Halo, come true?

1•sprhawk•7m ago•0 comments

Comrak: A CommonMark and GFM compatible Markdown parser and renderer in Rust

https://github.com/kivikakk/comrak
1•fanf2•7m ago•0 comments

Short alphanumeric pseudo random identifiers in Postgres

https://andyatkinson.com/generating-short-alphanumeric-public-id-postgres
1•shayonj•9m ago•0 comments

Proceed with Caution: Balancing the Allure of Tech Fads (2016)

https://insight.ieeeusa.org/articles/proceed-with-caution-balancing-the-allure-of-tech-fads/
1•mooreds•10m ago•0 comments

The coolest Unicode versions of every letter (A–Z)

https://fontgenerator.cool/abc-in-different-fonts
1•liquid99•13m ago•0 comments

Rolldown-Vite

https://voidzero.dev/posts/announcing-rolldown-vite
1•mooreds•15m ago•0 comments

Google admits it 'incorrectly removed' Kirkland business from its search engine

https://www.king5.com/article/news/local/google-admits-incorrectly-removed-kirkland-business-from-parts-search-engine/281-bc55e172-9946-481c-9c52-ed388992ba54
1•freedomben•15m ago•0 comments

Acclimation of Osmoregulatory Function in Salmon

https://www.unm.edu/~toolson/salmon_osmoregulation.html
1•mooreds•15m ago•0 comments

Dozens of active and planned NASA spacecraft killed in Trump budget request

https://www.science.org/content/article/dozens-active-and-planned-nasa-spacecraft-killed-trump-budget-request
3•gammarator•16m ago•1 comments

Key takeaways from the MAHA commission report

https://www.axios.com/2025/05/22/maha-commission-report-rfk
1•gmays•17m ago•0 comments

Show HN: LaminarFlow – AI-native, open-source finance platform for startups

https://www.lamflo.xyz
2•ydew•18m ago•0 comments

Can this self-driving electric bus make Riverside the new Detroit?

https://www.latimes.com/california/story/2025-05-15/riverside-self-driving-buses
1•PaulHoule•20m ago•0 comments

Let a Steam Locomotive Run Through Your Terminal

https://commandmasters.com/commands/sl-common/
1•ColinWright•20m ago•1 comments

Erasure cooling, control, and hyperentanglement of motion in optical tweezers

https://www.science.org/doi/10.1126/science.adn2618
1•bookofjoe•21m ago•0 comments

Show HN: Phended – Defensive Cybersecurity Education for Non-Tech Folks

https://www.phended.com/
1•fathermarz•22m ago•0 comments

Ask HN: Anyone making a living from a paid API?

2•meander_water•26m ago•0 comments

Show HN: Fontofweb – Discover Fonts Used on a Website or Websites Using Font(s)

https://fontofweb.com
10•sim04ful•29m ago•3 comments

There is an "imminent" threat to Taiwan, America warns

https://www.economist.com/asia/2025/05/31/there-is-an-imminent-threat-to-taiwan-america-warns
1•Ozarkian•29m ago•0 comments

Apache HertzBeat is a real-time monitoring system

https://github.com/apache/hertzbeat
2•Brajeshwar•29m ago•0 comments

James Webb Space Telescope discovers the earliest galaxy ever seen, MoM z14

https://www.space.com/astronomy/cosmic-miracle-james-webb-space-telescope-discovers-the-earliest-galaxy-ever-seen
1•Brajeshwar•29m ago•0 comments

Which New Language Should I Learn for Web Development?

https://mtlynch.io/notes/which-new-language/
1•Brajeshwar•30m ago•0 comments

China's Startups Race to Dominate the Coming AI Robot Boom

https://www.bloomberg.com/features/2025-china-ai-robots-boom/
1•helsinkiandrew•34m ago•1 comments

World’s Largest Hackathon

https://worldslargesthackathon.devpost.com/
1•dawie•36m ago•0 comments

Atlas: Learning to Optimally Memorize the Context at Test Time

https://arxiv.org/abs/2505.23735
2•og_kalu•37m ago•0 comments

The sound of broadcasting – Geoffrey G. Gouriet's Christmas Lectures (1972) [video]

https://www.youtube.com/watch?v=aBmMx80Vw-Y
1•CodeBeater•39m ago•0 comments

Blackned: Digitalisation of Armed Forces

https://blackned.de/de/
1•doener•42m ago•0 comments

Marine Life Encyclopedia

https://oceana.org/marine-life/
2•mooreds•46m ago•0 comments

The Two Ideals of Fields

https://susam.net/two-ideals-of-fields.html
7•susam•50m ago•1 comments
Open in hackernews

Modern C++ – RAII

https://green7ea.github.io/modern/modern.html
42•green7ea•1d ago

Comments

growlNark•1d ago
> Embracing Resource Acquisition Is Initialization (RAII) makes C++ the safest, most productive and fun C++ has ever been.

This seems like an extremely low bar.

Anyway, what use is there for C++ in 2025 aside from maintenance of legacy codebases and game engines? Off-hand I'd say C++ programmers are twice as expensive as rust programmers for the same semantics, and then you're still stuck with a C++ programmer you need to figure out how to socialize with.

motorest•1d ago
> This seems like an extremely low bar.

Is it, though? Most mainstream languages fail to support anything resembling RAII, at least as first-class support. Do you actually have an example of a language that does a better job at resource management than C++?

asyx•1d ago
Rust simply because the constructor being a static method on the type that can return basically anything including optional and result types and copy / move semantics are handled very easily through macros instead of constructor / assignment operator overrides.
motorest•1d ago
> Rust simply because the constructor being a static method (...)

This assertion makes no sense. RAII is not defined by whether you use factory functions or special member functions to initialize an object. In fact, RAII is only incidentally related ro memory management. RAII is a strategy to manage any and all types of resources, ranging from memory management to even files and TCP connections, by leveraging assurances that the runtime provides regarding scopes and object life cycles. None of this changes if you employ factory functions to initialize resources.

palata•1d ago
Not that I agree with the condescending parent (e.g. "you're still stuck with a C++ programmer you need to figure out how to socialize with"), but...

> Most mainstream languages fail to support anything resembling RAII

Wikipedia says: "RAII is associated most prominently with C++, where it originated, but also Ada,[3] Vala,[4] and Rust"

> Do you actually have an example of a language that does a better job at resource management than C++?

They don't necessarily offer a pattern like RAII, but what about "try-with-resources" in Java, or "use" in Kotlin that goes with `AutoCloseable`?

And what about "using" in C#?

What about "defer" in Swift?

I find those simpler than RAII.

pjmlp•1d ago
One caveat though, you need to pair those with static analysis tooling, if you want to ensure developers don't forget to make use of them.
palata•1d ago
How does RAII solve that? Developers can "forget" to use RAII, right? Or are you saying that it's easier to spot because RAII requires quite a bunch of boilerplate (whereas a one-liner like "defer" is easier to forget)?

Not criticising, really trying to understand :-).

pjmlp•1d ago
RAII when supported natively by the language, is done at the implementation level, not the usage point.

So in languages like Rust, D, Ada, Swift, C++, the compiler will do the rest unless you go out of your way to avoid the call to take place, like placing a value type on the heap using plain pointers.

With the other approach, even if you implement IDisposable, AutoCloseable, ContextManager and similar, you have to remember to manually write the code pattern that takes care of calling close(), or whatever the method/function happens to be called.

In languages with good support for FP patterns, like trailing lambdas, currying and such, there is another pattern, that is much safer, in case you don't want a static analysis tool to track resource usage, the with pattern.

You do something like withDBConnection connection (fun db -> all related db operations).

Assuming the lambda doesn't do naughty things to have db parameter escape the scope, the withDBConnection function will take care of handling the whole connection lifecycle.

znkr•1d ago
I agree, this is a real benefit of RAII compared to defer. That said, there are disadvantages of making the resource freeing part invisible. Not having to debug destructors that do network IO (e.g. closing a buffered writer that writes to the other side of the world) or expensive computation (e.g. buffered IO writing to a compressor) is a define plus. Don’t get me started on error handling…
motorest•22h ago
> I agree, this is a real benefit of RAII compared to defer. That said, there are disadvantages of making the resource freeing part invisible.

RAII doesn't make resource freeing invisible. It makes it obvious, deterministic, and predictable. The runtime guarantees that, barring an abnormal program termination that's not handled well, your resource deallocation will take place. This behavior is not optional, or requires specifying ad-hoc blocks or sections.

motorest•1d ago
> Wikipedia says: "RAII is associated most prominently with C++, where it originated, but also Ada,[3] Vala,[4] and Rust"

From those you listed, only Rust can be described as mainstream. Do you think that one out of a couple dozens refutes the statement that "most mainstream languages fail to support anything resembling RAII"?

> They don't necessarily offer a pattern like RAII, but what about "try-with-resources" in Java, or "use" in Kotlin that goes with `AutoCloseable`?

Try-with-resources and the disposable pattern offer similar features but they still fall a bit short. Unlike RAII, they are not thread-safe, require specialized syntax and boilerplate code, and require manually specifying scopes.

But even if you consider try-with-resources and Disposable pattern as a perfect replacement of RAII, now point out how many mainstream languages support them. You have Java and JVM languages, you have C# and .NET languages, Python, and...

> I find those simpler than RAII.

Arguably this boils down to personal taste, but RAII actually ensures your resources will be released, and you can tell exactly when this will happen. Disposable patterns don't, and screwing up a using with statement is all it takes to get your application to leak resources and fail silently.

tialaramex•1d ago
Obviously a language with linear types is just better at this, such as Austral.

In terms of languages you'd actually deploy today Rust is better both at this narrow feature and more broadly.

znkr•1d ago
When I switched from C++ to a bunch of other languages, I missed RAII initially. However, I quickly learned that other languages just do it differently and often even better (ever had to check an error when closing a resource?). Nowadays, I think that RAII is a solution to a C++ problem and other languages have a better solution for resource management (try-with-resources in Java, defer in Go, with in Python).
motorest•1d ago
> However, I quickly learned that other languages just do it differently and often even better (ever had to check an error when closing a resource?).

I don't think that's even conceptually the same. The point of RAII is that resource deallocation is ensured, deterministic, and built into the happy path. Once you start to throw errors and relying on those to manage resources, you're actually dealing the consequences of not having RAII.

oytis•23h ago
> try-with-resources in Java, defer in Go, with in Python

Or 'goto error8;' in C. Still RAII is much more convenient, especially for cases where you allocate a lot of interdependent resources at different time points. It keeps deallocation logic close to allocation logic (unlike, say, defer), makes sure deallocation always happens in the reverse order of allocations and doesn't force you to create a nested scope each time you allocate a resource

pjmlp•23h ago
Ada/SPARK, with better ergonomics than Rust, but its use will stay niche in high integrity computing.
pjmlp•1d ago
For one, the compiler and runtime implementation of the language you might happen to use, that that includes Rust.
oytis•1d ago
Where are C++ programmers paid better than Rust programmers? I thought Rust salaries are being driven high by all the crypto/fintech companies + scarcity
bluGill•1d ago
productivity counts not hours. If you can get the same work done faster then you cost to the company is lower even - possible even if your salery is higher.

though it isn't clear how much of rust's increased productivity is caused by being a new language where the architecture mistakes of the past decades are not slowing you down. We will need several more decades to answer that.

flohofwoe•1d ago
> stuck with a C++ programmer you need to figure out how to socialize with.

You're obviously trolling, but:

IME Rust attracts the same 'difficult' characters that are also attracted to C++ (because both are 'puzzle solving languages' instead of 'problem solving languages') the typical Rust coder may be even worse because of the missionary fervor and 'holier than thou' attitude.

oytis•1d ago
Puzzle-solving languages are rather Lisp or Haskell. Both C++ and Rust are very practical for their problem domain.
djmips•1d ago
Oh no, C++ has template meta programming and the ability to mask a DSL as advanced architecture, and then you can even implement Lisp or pick your favorite while claiming you're coding in C...++
sesm•1d ago
IDK about Haskell, but iterating in REPL with Lisp is the most practical form of programming I've experienced. In other mainstream practical languages this approach is reintroduced as a productivity tool like Quokka, etc.

C++ was practical some decades ago (hardware-friendly variant of OOP for GUI), but it failed as a library language and the domain where it's practical on modern hardware is much smaller. I will not say anything about Rust.

delta_p_delta_x•1d ago
> but it failed as a library language

This is very inaccurate. Essentially every high-performance library, user-mode driver, desktop application, and more is written in nothing but C++. Give me any library you can think of, and I assure you it is written in C++ (or maybe C, but this is masochism on the part of the developers). Even libraries for other languages like numpy, pandas, pytorch, etc are written in C++.

flohofwoe•1d ago
> or maybe C, but this is masochism on the part of the developers

C is the better choice when interoperability with other languages is needed (technically: a C API, the implementation language doesn't matter - but if a C++ implementation is wrapped in C API as an afterthought the result is usually a shitty C API). Personally I switched to C from C++ for writing libraries ca 2017 and don't regret that decision one bit.

Also, many C++ coders only have a foggy idea how convenient working in modern C can be, because their idea of C is usually the 'common C/C++ subset' that exists in C++, and this is stuck deep in the early 90s (for instance the designated-init feature in C++20 is a mere shadow of what C99 designated-init can do - to a point that the C++20 version is pretty much useless for real world usage).

delta_p_delta_x•1d ago
> only have a foggy idea how convenient working in modern C can be

Here is a list of C++ features that C doesn't have, that are an immediate deal-breaker for me:

  - reference and move semantics
  - templates, and type constraints with concepts
  - namespaces
  - `constexpr`, `consteval`, and other compile-time magic
  - `auto` type deduction
  - trailing return types 
  - RAII (can't believe I put this this late, but eh)
  - a passable (although still not perfectly complete) standard library that blows the C standard library out of the water
  - improved semantics that allow programmers to reason about the logic in code better, than obsess over pointer arithmetic
  - built-in virtual functions, function pointer tables, etc
I can list more, but this is going to end up as a list of 'essentially every feature in C++ that isn't in C', which is the very reason for the former language to exist.
flohofwoe•22h ago
...now who's the "masochist" here ;)
oytis•1d ago
Repl is cool, but Python also has a repl, and has a much more intuitive programming model (and much fewer braces).

Totally agree about the domain - no one is writing enterprise applications in C++ these days, luckily. It still does have its domain though, where there is not much choice apart from C++ or Rust (or C if you are a dinosaur)

ninkendo•1d ago
> the typical Rust coder may be even worse because of the missionary fervor and 'holier than thou' attitude

Anecdata, but the number of times I actually encounter these missionary Rust coders (the RIIR types) is utterly dwarfed by the number of times I hear people complaining about them. The memes making fun of the insufferable rust evangelists are at least 10x as prevalent as the evangelists themselves.

BoingBoomTschak•1d ago
Once Qt is properly accessible in Rust, I think your claim will be a lot more realistic. This goes for other important C/C++ libraries (e.g. libavcodec, vips/ImageMagick, VTK) without a solid (maintained, documented, etc...) Rust interface.
tialaramex•1d ago
Qt is a C++ kitchen sink library - perhaps it feels very important to C++ programmers but I can't imagine Rust people are looking forward to having more redundant types that do exactly the same thing as a type they've used for years but like, now with a Q in their name.

The fact that lists like yours so often end up being "Look at all these C libraries" ie not actually about C++ at all is revealing. It's an endorsement of Bjarne's position that he needed that C compatibility, decades later C++ alternatives remain unpopular but it also tells you that you're never going to raise the bar this way. C++ is not a route out.

AFAIK there is no equivalent of rustls-openssl-compat for C++. The knowledge that this library (OpenSSL) is trash never spurred any C++ programmers to do better and provide the same ABI but with a C++ implementation.

BoingBoomTschak•14h ago
What's your point? There's a lot to criticize about these libraries, but the fact remains that they're considered important and basically impossible to rewrite from scratch. Of course, Rust could get a rock solid portable GUI toolkit that doesn't rely on a webview (probably not much harder than wrapping Qt, to be honest), but it's not there yet.

I'm not in love with them or the abomination known as C++, if that's what you're implying.

tialaramex•14h ago
> basically impossible to rewrite from scratch

How so? This definitely needs at least a citation of somebody who can explain in detail why this code is "impossible to rewrite". Who wrote the one we have now, Martians?

ogoffart•8h ago
> Rust could get a rock solid portable GUI toolkit that doesn't rely on a webview [...], but it's not there yet.

What would you say is missing in Slint?

> probably not much harder than wrapping Qt, to be honest

There are already Qt bindings for rust (cxx-qt, qmetaobject-rs). What's missing from these?

green7ea•1d ago
Author here, I do prefer a language like Rust that makes all of this automatic but that isn't always an option. There are other parts of Rust that can be hard as well.

I wrote this article for a few friends who have recently started working with an existing, large C++ code base. Some industries like the video game industry have also stuck to C++ (they have their reasons).

A good programmer can work within the given constraints to make a useful program — sometimes, one of those constraints is the choice of language.

kjuulh•1d ago
I am by no means a C++ expert, a noob rather. It might be possible to make this generic, but it seems quite easy to forget a small detail here, and then be kneecapped because you forgot one of the overloads. So that in very few amount of edge cases your abstraction isn't actually cleaned up.

Better than nothing, and might be the most preferred way of doing things in C++, but it does seem dangerous to me. ;)

znkr•1d ago
I used to program a lot in C++ but switched to a number of different programming languages since then. Everything in C++ is this way and it’s hard to understand that things don’t have to be this way when you’re in the trenches of C++.
jiggawatts•1d ago
I distinctly remember what a breath of fresh air it was to switch to Java and then later C# where in both languages an "int" is the only 32-bit signed integer type, instead of hundreds of redefinitions for each library like ZLIB_INT32 or whatever.
pjmlp•1d ago
Now you can enjoy native ints on C#, as they improved C# for low level coding tasks.
jiggawatts•1d ago
"Native" types like usize and isize as used in Rust I'm totally fine with.

What I got frustrated with in C/C++ is the insanity of each and every third-party library redefining every type. I understand the history and reasoning behind this, but it's one of those things that ought to have been fixed in the early 2000s, not decades later when it's too late.

orwin•1d ago
I think by C++17 (14 even), it was in a very good state and since then, third party libraries are better and better. So really, a decade and a half later than you think it should have been.
bluGill•1d ago
It is possible, but it isn't hard to remember the rules. The scope of where you can mess up is isolated to the single class so it is generally possible to get this right. Manual memory management is easy when the new and delete are near each other, but you often need them far removed. RAII ensures the places you can mess up are close.

A static analisys tool can enforce the rule as well- you should have one.

unfortunately though this is one area that because c++ predates RAII it can't changethe defaults without breaking a lot of code. I am saying the problem is manageable - there is a real problem though. If you make a new language learn from this mistake.

pjmlp•23h ago
How can C++ predate the idea it helped to make mainstream regarding resource usage on the 1990's?
bluGill•21h ago
RAII was something that C++ incidentally made possible. Nobody realized the power until after C++ existed. It was more of a "look at the cool thing we can do" when C++ was invented, only after did people realize just how great/powerful it is.
pjmlp•20h ago
So C++ made the idea possible, it did not predated it.

The Design and Evolution of C++ is quite clear on how this process came to be, during C++ design as language.

bluGill•18h ago
kind of both as I understand it. Destructors was something C++ was going for, but the full power doesn't seem to be something that was really understood for a long time after they existed. At least not in C++ as I remember it in those days. Maybe Bjarne has a better vision that my professors didn't share though.
pjmlp•18h ago
They certainly didn't, because using destructors for RAII was already something I learnt in Turbo C++ 1.0 for MS-DOS manuals, back in 1993.

And by the time of Windows 3.x with OWL, Apple AppFramework, OS/2 CSet++, Motif++, they were used all over the place.

Easy to check those surviving manuals.

Also in 1995, the C++ lecture material at the university, back when everyone was implementing their own personal standard library, already discussed RAII design.

To note that even now there are plenty of universities that fail on their approach on how to teach C++, hence the Kate Gregory's talk aptly named "Stop teaching C" in the context of teaching C++.

green7ea•1d ago
C++ is a difficult language to use well but it becomes a lot easier when you turn on the 'correct' warnings. Turning on the `-Wdeprecated-copy-dtor` warning would help you not forget one of the cases in the rule of 3.

I would have loved it if this warning was on by default but sadly, you have to know to turn it on.

90s_dev•1d ago
Are are all the ideal warnings?
green7ea•1d ago
As far as I know, many experienced C++ programmers have a list of warnings they use for their projects and it varies by industry since different compilers will have different flags. When I was working on bigger C++ projects, one of the senior programmers would configure the warnings for everyone.

An easy start is to use `-Wall -Wextra -Wpedantic` for gcc and clang compilers. I would now add `-Wdeprecated-copy-dtor` to the list but I only learned about it writing this article.

90s_dev•1d ago
Why don't we just use shared_ptr most of the time? Is it really that inefficient?
ajross•1d ago
For the same reason that you don't use Rc for everything in Rust. Putting all your heap management behind reference counted pointers isn't "that inefficient", no. But if you don't need the direct control over heap behavior, you shouldn't be using C++ (or Rust) in the first place.

Languages with GC-managed runtimes (Java, C#, Go, Swift, et. al.) are actually significantly more performant for almost all heap-bound use cases, actually. Reference counting kinda sucks for typical code.

pjmlp•1d ago
Manual reference counting to be more precise.

When a GC-managed language uses reference counting as implementation algorith, the compiler might be able to optimize the reference counting to only occur when it is unavoidable or too costly to reason about, in a similar vein to bounds checking.

When using library types for reference counting, there is no way for the compiler to implement such optimizations, unless the types are somehow tagged with compiler intrisics so that they could apply the same kind of optimizations.

ninkendo•1d ago
> When using library types for reference counting, there is no way for the compiler to implement such optimizations

Aren’t refcounts in shared_ptr done as part of the copy constructor and destructor? It seems like vanilla copy elision would count as optimizing away the refcounts.

pjmlp•1d ago
Copy constructor, destructor, move constructor, copy constructor.

All of them have to do counter booking, value count and accessors, also possibly handle weak_ptr booking.

Plus how it actually works isn't part of ISO C++, so you're betting your luck on how a specific C++ is actually going to implement it, and possible issues when compiler versions change, same compiler or to another one.

ninkendo•1d ago
C++17 has copy elision as part of the standard now, so you can be guaranteed of the scenarios where C++ is required to outright skip the copy/move/destruction, leaving no code paths left for any refcounts. It’s not everything, there’s still plenty of optimizations on the table, but copy elision should eliminate a ton of refcount bookkeeping.
pjmlp•23h ago
In some scenarios, there is a reason why there a few conference talks on the gotchas regarding that, especially when coupled with RVO.
ninkendo•1d ago
> Languages with GC-managed runtimes (Java, C#, Go, Swift, et. al.)

Swift does not have a GC managed runtime in the same sense as the other languages you listed [0], it’s basically a bunch of refcounts inserted by the compiler, with similar performance characteristics to Arc in Rust or shared_ptr in C++. (For classes, at least. Structs are value types and stack-allocated.)

[0] Yes, automatic refcounting is a form of garbage collection, but Java/C#/Go use tracing GC’s and not direct refcounting, whereas with Swift it’s more like the compiler is wrapping all objects in a shared_ptr for you, and so destruction is explicit and happens at exact points.

oytis•1d ago
Why, we do. Whenever there is data on heap that needs to be shared that is
znkr•1d ago
It’s mostly fine, until you run into memory leaks due to circles or because some part of your program holds onto the root of some large shared pointer graph and you have no idea which part. If you take it very far, like some code bases I worked with did, you discover that everything needs to be shared pointer now, because most lifetimes are no longer explicit but implicitly defined by the life time of the shared pointer that holds it.
flohofwoe•1d ago
Because shared_ptr (and also unique_ptr) nudges you towards keeping each object in its own heap allocation, and that quickly gets inefficient with large number of objects. E.g. a handful of large objects managed through shared_ptr is usually fine, but managing many tiny C++ object individually through smart pointers usually isn't. Instead store large groups of objects of the same type and similar lifetime by value in a std::vector (and then maybe put that std::vector behind a smart pointer).

Also if you lean in too much on shared/unique pointers for large amounts of tiny objects you'll most likely end up in a situation where Java-style garbage collection would be more efficient.

E.g. manual or semi-manual memory management is mostly about controlling the overall memory layout of your application's data to improve throughput, reducing the number of individual heap allocations is just a useful side effect.

bluGill•1d ago
Most of the time unique-ptr is faster and makes it easier to reason about your program. There is more than heap managemant to performant code and shared ptr makes it harder to reason about those other areas.
fh973•1d ago
Yes, it is very inefficient, as it is thread-safe and uses atomic operations internally.

So instead of just accessing memory, you have the cost of cross-cache coherency operations between CPU cores.

William_BB•1d ago
I take the following approach: - Stack by default - Unique ptr if needed on the heap - Shared ptr if needed to share ownership

Although unique ptr is zero cost after make_unique(), I avoid polluting my heap unnecessarily. I've never benchmarked this though (keeping various objects on stack vs heap as unique ptr and how that impacts memory accesses)

I'm quite junior. Appreciate anyone pointing out if anything I said doesn't make sense.

green7ea•1d ago
Author here, that's a good approach :-). I see shared_ptr as a code smell since shared ownership makes life difficult.
grues-dinner•1d ago
> Stack by default - Unique ptr if needed on the heap - Shared ptr if needed to share ownership

Sounds about right. Shared ownership is fairly rare though, and you often only need shared access (reference/pointer if nullable) and can provide other, more explicit, ways of managing the lifetime.

> unique ptr is zero cost after make_unique()

Kind of, but compared to the stack, it could cause caching inefficiency because your heap-allocated thing could be almost anywhere, but your stack-allocated thing is probably in the cache already.

grumbel•1d ago
With shared_ptr you completely lose track who actually owns an object or when it will get destructed. It encourages sloppy programming and makes code much harder to read and reason about.

Unlike most languages that have ref-counting build in, shared_ptr also doesn't provide anything to deal with cyclic dependencies, so you can end up with memory leaks.

The most important reason however is simply that you don't need it like 99% of the time, unique_ptr provides enough functionality to work just fine as a shared_ptr replacement in most situations. And in the rare cases where you really need a shared_ptr, you can just convert a unique_ptr into one.

green7ea•1d ago
Author here, parent comment describes it very well — shared_ptr are a last resort, not a first one.

They are quite heavily (and badly) used in some code bases (ROS). I'm planning a future article that covers shared_ptr in more details.

The surprising thing about shared pointer is that a `const shared_ptr<T>` means that you can modify the contents of T. This makes the problem, mentioned in the parent, of keeping track of who can modify the object where impossible. I've never encountered a `const shared_ptr<const T>` but that would be a better approach.

rjinman•1d ago
unique_ptr is much better because then each object has a sole owner, which makes object lifetimes much easier to reason about and you can't end up with cyclic references causing memory leaks.
majoe•1d ago
Reasons I can think of:

- Wrapping all objects in shared pointer is annoying. - If you stick to that convention, you have to do it on every call side, while you only have to implement RAII once. - You can enforce invariants of your class with RAII, that you can't with a plain shared_ptr - Regarding efficiency: It has the overhead of reference counting plus you have to store all objects on the heap instead of the stack. In hot loops this may hurt cache locality.

yahoozoo•1d ago
The color/holding all over this article is annoying.
green7ea•1d ago
Author here, I put that in place for people who skim articles or paragraphs — this is a surprising amount of people.

Would it be better if it was more subtle? Were you reading in dark or light mode?

yahoozoo•22h ago
Probably just less of it. I see bolding like that and find myself clicking on them thinking they are links. It seems like a few of them actually do have links though.
green7ea•19h ago
Thanks for the feedback, I removed the text highlighting. Hopefully it reads better.

You might have to control+f5 to see the changes, I had to.

pjmlp•1d ago
It is a diservice to C++, to paint RAII as modern C++.

We were already making use of RAII in C++ compilers for MS-DOS during the C++ARM (the C++ equivalent of K&R C book), one such example would be Turbo Vision C++ variant and Borland International Datastructures Library (BIDS).

If anything, it is a pity that 30 years later, it is still something we need to educate people about, as it isn't as adopted as it should be.

EDIT:

If this is supposed to be Modern C++, at the very least provide C++23 example in 2025, instead C++ from 2011.

Meaning import std, using a custom deleter in std::unique_ptr (it doesn't manage only heap types), making use of =default to get back compiler generated member functions, as it would do the right thing in the example for the fd handle.

grues-dinner•1d ago
Modern C++ does give you move semantics, which makes RAII a lot more expressive, especially with smart pointers.

One things about RAII that I find is that, a bit like inheritance, it's actually not something you have actually do nearly as much as the emphasis it gets in the first chapters of all the books implies. How often do you actually write a move constructor or even a destructor in workaday code? Most of it is done for you by the stdlib (unique_ptr, say) or libraries. Of course it needs to be understood, and understood well, but it feels like landing a plane: you have know it well and it's not unusual and certainly not wrong, but also flying is mostly doing things other than landings.

tialaramex•1d ago
The C++ 11 move is terrible because it's not the move semantic people actually wanted - which is what people took to calling "destructive" move, the feature Rust provides - instead it's this weird confection where we're scooping the guts out of one object and transferring them into a new object, leaving something hollow behind in order to satisfy the requirements of 1980s C++ programs.

In some cases this can be optimised to the same machine code, but not always, and semantically it's not what we actually wanted anyway. In terms of RAII this means arranging that after the move the "moved from" object remembers it no longer has any resources and so when it is destroyed it won't clean up - much easier to just design the language properly.

ninkendo•1d ago
RAII, like a lot of C++ concepts, finds the most use in library-like code (stdlib especially), where it needs to be super generic. Application developers get the benefits of these concepts by simply using these libraries, even if they don't have to care about them themselves. As an application developer, you mostly focus on classes as plain-old-data and functions to work on them, so you don't need to mess about with custom destructors or move-constructors or other RAII stuff.
stingraycharles•1d ago
There’s still a huge part of the industry that writes a mix of C-style C++.

Modern C++ is all about template metaprogramming, concepts, move semantics, ranges, etc.

But there’s a significant cognitive load will all of that.

bluGill•1d ago
The term modern C++ means RAII. Those other things are common and sometimes useful in new code that can use them. However anyone who says 'modern C++' is talking about RAII not those other things.
pjmlp•23h ago
Already possible in C++ARM, as any look into 1990's C++ frameworks documentation on digital archives would prove, regarding RAII.

Or even articles in The C/C++ Users Journal, Dr Dobbs, PC Techniques, Microsoft Systems Journal.

Unfortunately many that write C with C++ compilers, only started paying attention around C++11.

bluGill•21h ago
The term Modern C++ predates C++11. C++11 gave us move constructors which makes RAII much more powerful, but we were doing it for a long time in C++. Well some of us were doing it, there are a lot of people who are writing the type of code that gives C++ a bad name (even today)
stingraycharles•3h ago
Isn’t “modern” a term that’s relative to the current time, rather than a fixed point in time?

Like, modern architecture, fashion, cuisine all change over time.

Why would “Modern C++” refer to a fixed point in time somewhere in the 90s?

green7ea•1d ago
Author here, what you say is entirely correct — I didn't emphasize enough that this was all possible before in a more limited way. Those parts were cut out to try to make the article more focused on understanding RAII.

The modern parts covered in the article are the move semantics making RAII more expressive and the standard library embracing the concept throughout.

I think the idea of modern is to convince everyone to give these 'new' techniques a try if they aren't already using them.

pjmlp•1d ago
It is always a good thing to spread knowledge, however when C++11 is modern, what C++14, C++17, C++20, C++23, C++26 are supposed to be?

There are already plenty of memes on C++ conferences regarding that.

einsteinx2•1d ago
> what C++14, C++17, C++20, C++23, C++26 are supposed to be?

Postmodern C++?

pjmlp•23h ago
That would be C++14, if C++11 is the modern one.
green7ea•1d ago
I would see that C++11 started the modern C++ era and the later standards have refined and perfected it.

I would be very sad to have to go back to C++98, it would feel like a different language — I would only be inconvenienced to go back to C++11. Maybe ranges changes that ;-).

motorest•1d ago
> It is a diservice to C++, to paint RAII as modern C++.

I think you're missing context. The term "modern C++" is used to refer to idiomatic C++ introduced in C++11. It has been that way for a couple of decades.

https://learn.microsoft.com/en-us/cpp/cpp/welcome-back-to-cp...

The article touches on the topic of move semantics and move constructors. That's modern c++. That's not your C++98 RAII.

In the same vein, "modern CMake" is also the term used to refer to the declarative style that followed the release of CMake 3, which dates back years.

pjmlp•1d ago
I also own Andrei's book, first edition.
motorest•1d ago
Reading it is an option, then.
pjmlp•23h ago
More often than some of the HN readership was born.

I have been keeping my C++ skills up to date since 1993.

AlexeyBrin•1d ago
How many modern compilers will let you write import std; in a C++ file and build the executable without shenanigans ? GCC 15 still does not let you compile a C++23 code with:

    g++ -std=c++23 -fmodules foo.cpp
Without manually generating the std module first. Until all compilers will directly accept the import keyword it won't be adopted on a large scale by regular programmers.
pjmlp•23h ago
Visual C++ and clang.

Many projects do just fine sticking to a single compiler.

Not for everyone, but they exist nonetheless, including on FOSS world.

AlexeyBrin•19h ago
AFAIK, Clang (like GCC) needs an extra step to compile the standard modules files. It does not work, as one would reasonably expect, with something like:

    clang++ -std=c++23 fname.cpp
(I know you can use Cmake to solve it - but I want a simple solution something that can be shown to a junior programmer.)
nathell•1d ago
My pet peeve with C++ RAII is that it uses destructors for cleanup, so it can’t throw an exception from within the destructor if that fails somehow. E.g. from the manual page of close(2):

> A careful programmer will check the return value of close(), since it is quite possible that errors on a previous write(2) operation are reported only on the final close() that releases the open file description. Failing to check the return value when closing a file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.

Last time I checked, GCC’s implementation of ~ofstream() ignored failures from the underlying close().

flohofwoe•1d ago
This is also a problem when an object referenced by a shared_ptr is destroyed much later than expected because some obscure part of the code still holds a reference to the object.

That's why in many situations it makes sense to have an explicitly called discard() method, while the destructor is 'empty' and only checks that discard has actually been called.

Of course that also means that RAII isn't all that useful for such situations.

bluGill•1d ago
One more reason to aviod shared pointers. They are sometimes useful enough as to be worth it, but they make code analisys harder.
1718627440•1d ago
Why can't you simply call the destructor, where you would call discard?
flohofwoe•1d ago
Because there may still be shared pointers in the wild holding a reference to the object and the last of those will call also attempt to call the destructor.

With an explicit deinit() method you'd basically get an object that's in an deinitialized, but not destructed state (quite similar to the state a moved-from object is in), the object still exists in memory and can react with proper errors to attempts to access.

1718627440•1d ago
Is there a way to replace the object with a nullptr instead? Then you can call the destructor any time you like.
grues-dinner•1d ago
The whole point of a shared_ptr is that you can't delete it out from under other users. You can do exactly what you suggest with a weak_ptr.

A shared_ptr to an object with a deinit() is rather like a weak_ptr in that someone else can "delete" it, and you should check if it's really there, except it can still have some information about things like deinit failures rather than just telling you that the object is deleted.

1718627440•23h ago
In this case it is clearly intended to be deleted under users, so why not use the language feature for that (destructor) instead of inventing yet another level of book-keeping.
grues-dinner•21h ago
You can, as long as you don't need to know if/how something within the deinit failed. If you literally just want to know if the item is gone, that's exactly a weak_ptr.

File streams, say, do this by expecting users to close() the file themselves if they care if exceptions happen, but if you destruct without doing that first, any exceptions are caught and don't make it out of the destructor, so they're just gone and you'll never know.

90s_dev•1d ago
About a year ago I bought the official C++ book and read through it fully (including most of the reference part) after finding out that Animal Well was written in it. It honestly seems like a very good and interesting langauge, if carefully used, especially for games where memory can be allocated at startup and held forever. Kinda wish I had an excuse to write some C++.