Hacker News new | ask | show | jobs
by ryandrake 709 days ago
Just another person’s opinion: I’ve been using C++ for my entire career, and to be honest, if I’m starting a new solo project, I reach for it unless there is some major technical reason not to. Yes, it can be messy. Yes, there are footguns. But as a developer, you have the power to keep it clean and not shoot the footguns, so I’m still ok with the language.

If I was starting a new work project with a lot of junior team members, or if I was doing a web project, or a very simple script, fine I’ll use a different language. There can definitely be good reasons not to use C++. But I’m at the point in my expertise that I will default to C++ otherwise. I’m most productive where I am most familiar.

3 comments

> Yes, there are footguns. But as a developer, you have the power to keep it clean and not shoot the footguns, so I’m still ok with the language.

With all due respect to your expertise, the whole idea of a footgun is that it tends to go off accidentally. The more footguns a language contains, the more likely you are of accidentally firing one.

I think what he's saying is that C++ users don't need to go to the Footgun Outlet Mall and wantonly brandish each of their credit cards. You can leave the subtle parts of the language on the shelf, in many cases.
> I’ve been using C++ for my entire career, and to be honest, if I’m starting a new solo project, I reach for it

This is “I use the language I always use because I always use it”, and not actually a praise or C++ specifically.

Presumably "entire career" means some amount of exposure to other things.

In my 21 years coding professionally, I will settle on C++ or Ruby for most problems depending on context. Ruby for quick, dirty, and "now!", while I use C++ for Long lasting, performance, strongly typed, and compatible things. Those aren't perfect categories and there are reasons to pick other tools, but Choosing C++ after a long career does mean something more than "I am comfortable with this".

> Choosing C++ after a long career does mean something more than "I am comfortable with this

Does it?

Yes, feel free to re-read the all the rest of the comment where share a little bit of experience, and try to understand that people other than you have experience.
I did, it was yet another “I use it because I always use it” post, but longer. Absolutely 0 value.

But if you’re going to behave like a child I’ll skip the rest. Enjoy!

Thank you for agreeing to leave the discourse. It it shall be much improved through your action.
"you have the power to keep it clean and not shoot the footguns". Really? Do you think footguns are intentionally shot?
There are more an less risky behaviors. This is really well explored space in C++. Just using value semantics, shared_ptr, and RAII instead of naked news and reckless mallocs would improve several "old" codebase I have worked in. Maybe people shouldn't be reaching for const_cast so often, and similar. In some new languages some corner case may be unexplored.

If you are fortunate enough for your domain to have good IO libraries then there is a chance you can do everything the "Modern" way avoid a lot of the headache and avoid most of the footguns entirely. That maturity and omni-pattern availability is potent, but all that power does come with the possibility of mistakes or surprises.

Compare to newer languages where we don't know what might break or might need to do something the language omits as part of its paradigm. I have done a ton of Ruby projects and about half the time we need more performance so I need to bust out C to rewrite a hotspot in a performance sensitive way. Or sometimes you just really want a loop not a functional stream enumerator like is the default in Ruby. For a new language, Theo tried the 1 billion row challenge in Gleam and the underlying file IO was so slow the language implementers had to step in.

This is an engineering and a business choice. There are reasons to avoid C++ and footguns, like any risk, are among them. These aren't risks without mitigation, but that mitigation has a cost. Just like newer languages have reasons not to use them. A team needs to pick the tools with risks and other cons they can handle and the pros that help them solve their problem.

> There are more an less risky behaviors.

The problem is that your definition of risk may not be the same as others', and so there isn't always agreement on what is ok and not ok to do. And regardless, humans are notoriously bad at risk assessment.

> This is really well explored space in C++. Just using value semantics, shared_ptr, and RAII instead of naked news and reckless mallocs would improve several "old" codebase I have worked in. Maybe people shouldn't be reaching for const_cast so often, and similar.

Right, and all that is exactly the point: all of that stuff is in wide use out there, and I suspect not just in "old" code bases. So there's still not consensus on what's safe to use and what's too risky.

And regardless, I have enough to think about when I'm building something. Remembering the rules of what language features and APIs I should and shouldn't use is added noise that I don't want. Having to make quick risk assessments about particular constructs is not something I want to be doing. I'd rather just write in a safer language, and the compiler will error out if I do something that would otherwise be too risky. And as a bonus, other people are making those risk assessments up-front for me, people in a much better position than I am to do so in the first place, people who understand the consequences and trade offs better than I do.

I really like this value proposition: "if the compiler successfully compiles the code, there will be no buffer overruns or use-after-free bugs in it" (certainly there's the possibility of compiler bugs, but that's the only vector for failures here). For C++, at best, we can only say, "if you use only a particular subset of the language and standard library that the compiler will not define or enforce for you (find a third party definition or define it yourself, and then be very very careful when coding that you adhere to it, without anyone or anything checking your work), then you probably won't have any buffer overruns or use-after-free bugs." To me, that's almost worse than useless; even if I find a C++-subset definition that I think is reasonable, I'm still not really protected, because I still have to perfectly adhere to it. And even if I do, I'm still at the mercy of that subset definition being "correct".

You need to think about every language's rules and APIs when starting a project. You do raise valid concerns about C++ and those are real issues. Every language has real issues. Some have fewer up front and obvious choices, but they all have issues.

Choosing no to decide you still have made a choice.

What even is a footgun supposed to be? The analogy doesn’t really make sense, in that… I mean the first thing anybody learns about guns is that they are “always loaded” (even when you know they aren’t) and you only point them at things you want shot.

Is a footgun a gun that only aims at feet? Because that seems like a dumb thing to invent in the first place. Or is it a gun that happens a to be aiming at feet? That seems like something that could only exist by user error.

I think “enough rope to hang yourself” is a more accurate description of almost every programming languages, since rope is at least intended to be useful (although it is a bit more morbid of an analogy).

Imagine that you had a gun and one of the features of the gun was that if you had sunglasses on and something in your left pocket, holstering the gun would cause it to immediately fire. You could argue that the gun shouldn’t behave this way, but it’s also possible that others are dependent on this behavior and you can’t remove it.

This is a footgun - the way to avoid the holster firing is to simply not wear sunglasses, or keep something in your left pocket, and then it would never fire. But the problem is that both of those things are extremely common (for good reason). It’s a poorly thought out feature because it has severe consequences (potentially shooting your foot) for extremely common situations (wearing sunglasses and using your left pocket).

I basically don’t agree that anybody could depend on this holstering-causes-it-to-fire behavior. Or at least, their use-case requires design compromises that are so unthinkably ridiculous as to make the gun they want something that no reasonable person without that use-case would use.

It is possible that the entire field of programming is full of ridiculous people. But it seems more likely that C++ is like a gun with no safety, or something along those lines.

A lot of the footguns come from compiler authors wanting to make things UB because it allows them to perform certain optimizations, but then you end up with a lot of things that are formally UB even though in practice they usually do the intuitively expected thing. But then, because the widely done thing is actually UB, the compiler is allowed to do something counterintuitive which causes your program to blow up.

An obvious example is omitting NULL pointer checks. Passing a NULL pointer to certain system library functions is UB even if it would ordinarily be expected to be reasonable, e.g. memset(NULL, 0, 0), so some compilers will see that you passed a pointer to memset, and passing a NULL pointer to memset is UB, therefore it can omit a subsequent NULL pointer check guarding a call to something else when the something else isn't going to behave reasonably given a NULL pointer.

This is an insane footgun, but it also allows the compiler to omit a runtime NULL pointer check, which makes the program faster, so people who care most about performance lobby to keep it.

Just to carry onwards with the use/mention distinction we're aggressively erasing here, you seem to question whether actual, real-life footguns exist.

They do! Here's a reference. https://en.wikipedia.org/wiki/Slamfire

Another common way to shoot yourself in the foot is a gun which will go off if you drop it. An example of a gun where early models were especially susceptible is the Lanchester: https://en.wikipedia.org/wiki/Lanchester_submachine_gun

> I basically don’t agree that anybody could depend on this holstering-causes-it-to-fire behavior.

It's an idiom. It's not supposed to be entirely logically consistent. It means what it means because people have decided that it means what it means. Your objections aren't really relevant.

"Footgun" is I think a fairly recent addition to the English lexicon, but it's based on the centuries-old "to shoot yourself in the foot". It seems silly to argue with centuries of English idiomatic usage; no one, by definition, is going to win an argument against that.

Yeah I don't think that's a good analogy. Instead, you have guns that don't let you point at your feet. So you can never shoot yourself there. However, if you ever need to shoot straight down for a legitimate reason, you're out of luck. In C++, you can shoot everywhere without restrictions and sometimes that means shooting yourself in the foot or the head.
"Footgun" comes from the English idiom "to shoot yourself in the foot", which means "to act against your own interests" (usually accidentally). (Consider similar idioms, like "to dig your own grave".)

I think you're being a bit too literal. It's not an analogy at all, and this has nothing to do with firearms best practices. If we were to define a footgun as "a gun that is only capable of shooting you in the foot" (or perhaps more broadly usefully, "a gun that in theory can be useful, but it is nearly impossibly difficult to make it do anything other than shoot you in the foot"), then the entire point of using the term is to describe something that has no useful, logical purpose, and is unsafe to use, even as designed.

Being "given enough rope to hang yourself" is indeed another good idiom to use for things like this, but the implication is different, I think: when you're given enough rope to hang yourself, the outcome is still very much in your hands. You can intentionally or unintentionally use that rope to hang yourself, or you can be reasonably expected to use that rope in another way that would turn out to be safe or useful.

"Footgun", by contrast, is used to describe something that has no (or negligible) safe uses. Maybe the original intent behind the design of what's being described that way was to have safe uses, but ultimately those safe uses never really panned out, or were so dwarfed by the unsafe uses that the safe use isn't worth the thing existing in the first place. But, unfortunately, there are some people -- maybe only 0.01% of people -- who are able use it safely, and critically depend on that safe use, so we can't completely destroy all these footguns and save everyone else from the error of their ways. And unfortunately most everyone else sees these 0.01% of uses, and believes they are so useful, so efficient, so brilliant, they want to try it too... but in their hubris they end up shooting themselves in the foot, like most others before them.

I've long been partial to this formulation:

> 1972 - Dennis Ritchie invents a powerful gun that shoots both forward and backward simultaneously. Not satisfied with the number of deaths and permanent maimings from that invention he invents C and Unix.

Some of us learn to lean to the side right before pulling the trigger...

http://james-iry.blogspot.com/2009/05/brief-incomplete-and-m...

At this point a footgun can stand alone in this industry as a term with its own meaning outside of analogy.

It is any trap in something technical that is likely to cause problems from perceived normal use.

Compare to related terms: "Pit of failure", "Turing tarpit", and "Pit of success".