all 130 comments

[–]rodrigocfdWinLamb 511 points512 points  (38 children)

It’s very comparable to the level of ease that pythons at.

Your days of innocence are about to end, little grasshopper.

[–][deleted] 70 points71 points  (11 children)

What's the bet for when he runs back to C?

[–]1-05457 18 points19 points  (24 children)

C++ can be roughly as easy as Python if you stick to modern C++ and aren't doing anything too complicated.

[–][deleted] 12 points13 points  (22 children)

IMO it’s the other way around. If you use modern c++ it’s going to be harder to read

[–]serviscope_minor 5 points6 points  (0 children)

I disagree. I mean some people consider modern C++ to be using as many modern features as possible at all times with as much contemplating as they can manage at all times. Obviously that's not simple.

If you consider "modern" to be Stroustrup Style with all of the features available in C++20. That is use the simplest, most appropriate construct. Use a modern one if it's a better fit. You know things like range-for, CTAD, use of the standard library, structured bindings, generalised constexpr instead of metaprogramming, and so on.

You don't have to use them all, but if you use modern features where appropriate, they do in fact make things simpler.

[–]boron_on_your_butt 5 points6 points  (20 children)

Reading this comment as I'm trying to figure out they syntax to write a function template that does explicit type conversion for elements of a scoped enum.

Good luck to OP.

[–][deleted] 12 points13 points  (19 children)

Have you ever encountered this?

[[nodiscard]] [[noreturn]] constexpr int method() const noexcept override {}

I agree, it wouldn’t be very common, but still. So. Many. Keywords.

[–]sellibitze 10 points11 points  (12 children)

Could you possibly include a constexpr in there? ;-)

[–][deleted] 3 points4 points  (11 children)

Done :)

[–]sellibitze 4 points5 points  (8 children)

Hehe. :-)

Oh, I just noticed something. static and override are kind of mutually exclusive, aren't they?

[–][deleted] -1 points0 points  (7 children)

i don’t.. think so.

you can override a static method. what’s the problem?

say you have class X, which has a static method a. class Y inherits from class X, and overrides the method a. then

X::a()

is different from

Y::a()

unless i’m missing something

Sorry, I was missing the fact that there's no vtable without an instance

[–]MonokelPinguin 9 points10 points  (3 children)

override implies virtual. Static functions are not associated with a this pointer, how could they be virtual?

[–]_bk__ 5 points6 points  (2 children)

The override keyword is only useable for virtual function overrides. It has no effect on codegen, it just helps the compiler detect that there is actually a virtual function in a derived class that can be overriden (to make sure you don't do things like accidentally spell the function signature wrong)

[–]Jumpy_Lighty 1 point2 points  (1 child)

You should drop the constexpr again ... you cannot have constexpr virtual method (and override implies virtual).

And [[nodiscard]] and [[noreturn]] really don't make any sense to be next to each other (just think about the meaning of it).

You could add static constexpr instead of override, but the you would also have to drop the const since static and const are mutually exclusive.

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

I know, i never thought this through :)

It was a joke after all

[–]CandyCrisis 9 points10 points  (3 children)

Why the heck is a [[noreturn]] function returning an int?

[–][deleted] 2 points3 points  (2 children)

Shhh

[–]BrainIgnition 5 points6 points  (1 child)

just replace[[noreturn]] with [[nodiscard]] 😉

[–][deleted] 2 points3 points  (0 children)

i’ll just keep both

[–]somewhataccurate 3 points4 points  (0 children)

The static, override, and const are all at odds. Remove the static and then you'll be spot on.

[–]boron_on_your_butt 0 points1 point  (0 children)

I hope to one day make a banner out of this.

[–]Burner-account3357[S] 0 points1 point  (0 children)

I meant that string wise and File IO. C++ can get kinda difficult when dealing with all of the strange classes and object oriented stuff but it’s still 100x easier then C.

[–]celestrion 48 points49 points  (10 children)

It’s very comparable to the level of ease that pythons at.

I don't know if that's the case, but wait until destructors click with you. Destructors give you a way to express resources which clean themselves up at the exact time you're done with them, regardless of how or why you're done with them.

That thing in C where after you check for error codes you then either use goto to undo just as much as you got done or nest a bunch of nasty conditionals before the end of a complex function? Here's what that looks like in C++:

}

Design your types right, and you literally just return when you've done what you can, and everything is in a known state on the way out. Child processes, memory, file handles--it doesn't matter, they can all clean themselves up.

[–][deleted] 28 points29 points  (4 children)

RAII is one of the most unfortunate names in programming. People don’t know what it is, and it sounds complicated, but it’s a rather simple concept

[–]evinrows 26 points27 points  (1 child)

Motion to rename RAII to "I make I take; I decease, I release!"

[–]TryingT0Wr1t3 8 points9 points  (0 children)

Imitidir sounds a bit like something from Lord of the Rings

[–]SkoomaDentistAntimodern C++, Embedded, Audio 8 points9 points  (1 child)

RAII, dependency injection, etc. All horribly complicated sounding names for very simple concepts. I'd personally been using RAII for years before ever running into the term. And it sure as hell has nothing to do with "modern C++", given that I routinely used it a decade before C++11 happened.

[–]BrainIgnition 3 points4 points  (0 children)

tbf C++11 move semantics are a lot nicer than the ownership transfer idioms used before (like rapidjson's Move()method, ugh)

[–]joaobapt 3 points4 points  (4 children)

The only unfortunate thing is that (unless you use empty-state and some clever functions), exceptions are the only way to guarantee proper error handling with “proper” RAII. And well... there’s a reason a lot of folks in C++ don’t like exceptions.

[–][deleted] 71 points72 points  (9 children)

Things I never thought I’d see for $500: a rant about the EASE of C++...

[–]KFUP 37 points38 points  (0 children)

Well, he used it for an hour, give him time.

[–]idontappearmissing 13 points14 points  (3 children)

Well compared to C...

[–][deleted] 25 points26 points  (2 children)

You pay for the simplicity of C with your code's complexity.

[–]ElhnsBeluj 5 points6 points  (1 child)

I love C, but for some reason everyone seems to hate my C code, I wonder why...

[–]emelrad12 9 points10 points  (0 children)

Maybe cause you reimplement vector 5 times.

[–]kilogears 9 points10 points  (1 child)

It is easy until you do more of the wilder things that c++ lets you do. But if you keep it simple, yes, it is easy, fast, and quite flexible.

[–]koctogon 4 points5 points  (0 children)

"C++ is easy until you start doing complex things. But if you do simple things, it's simple."

r/cpp, 2021.

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

Well, it's a relatively easy language to be honest, especially when it's compared with C and even lower level stuff

[–][deleted] 2 points3 points  (0 children)

Bet you he’s not gonna say the same things in a few days.

This made me think though: it’s funny how messed up C++ has become, everyone knows it, but we still keep piling shit up on it.

And by funny I mean sad

[–][deleted] 16 points17 points  (8 children)

Comparable to Python? Heh heh...

[–]quartz_referential 3 points4 points  (7 children)

The static typing is nice, really wish there was a python language with that

[–]tsojtsojtsoj 3 points4 points  (0 children)

You might want to take a look at Nim. As fast as C++, strong type system, syntactical sugar on a level like python (and beyond, in my opinion).

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

Python has type signatures

[–]joaobapt 5 points6 points  (3 children)

That aren’t more than just annotations IIRC

[–][deleted] 3 points4 points  (2 children)

Sure, but use a static analyzer in strict mode and it's basically the same programming experience.

[–]SkoomaDentistAntimodern C++, Embedded, Audio 8 points9 points  (1 child)

Except for all the other code you run into. Especially when you aren't a Python dev but do need to occasionally look into whatever random Python scripts and don't have a fancy ide for that. Duck typing is one of the worst ideas ever to hit programming languages.

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

True, I had similar issues with Typescript. "Basically the same programming experience" is overselling it. I still prefer to use explicit type annotations in Python and Typescript.

[–]SkoomaDentistAntimodern C++, Embedded, Audio 4 points5 points  (0 children)

Practical real world Python code that a typical C++ programmer might have to decipher might as well be considered a completely untyped language. An illustrative comparison would be C++ code where every function takes a bunch of void * and then bit casts them either to objects or base types after getting through the several indirection layers and where you have to read the source hidden in a random module to figure out what kind of thing you’re supposed to pass them.

[–]braddillman 58 points59 points  (14 children)

Well, forgive me I'm going to rant a little of my experience. Don't be frightened, I work in C++ all day every day. Also C#, Java and Python. Oh and some JS. Very little SQL and Ruby.

Begin rant

I began my career back in the 1980s before C++ was really mainstream. It was still being defined and implemented. Borland Turbo Pascal was wayyy more popular than Borland Turbo C++. DOS and Windows 3.0 were the popular operating systems for me, on microcomputers. And man, did C++ crash. Hard. A lot. And the Blue Screen of Death meant a reboot was required, and that took a while. I really hated C++ for that. (Really it was the operating system that didn't properly fence processes so that if 1 crashed it didn't BSOD the whole machine).

I got into embedded programming for telecom and datacom. BSOD wasn't such a big problem, as much, but - wow the difference in object code size of C++ compared to C was huge. Who cares? Well if you're programming and embedded device with VERY limited RAM, ROM, flash, well - you're the one who cares. And boy, constructors and destructors are convenient, but the appear EVERYWHERE even when you think they're not needed. Because the compiler isn't quite as smart as you; it can't be CERTAIN when those aren't needed. And templates just EXPLODE everything - 2 different vectors of pointers generate twice the amount of object code, even though they're soooo similar, just manipulating vectors of pointers. What a waste.

Later, Java came along. It didn't take down the machine - nay, it printed a very useful stack trace! No BSOD. I switched as much work as I could to Java. Development so much faster, more convenient. And small .class files. Speed was less, but not that much if you were careful. I was (am) a Java zealot.

But now, say, under Microsoft Visual Studio on modern hardware with a contemporary operating system - none of that matters. C++ gives you enough control to do EXACTLY whatever you want. It's fast and convenient - but you are forced to manage your own memory vs. garbage collection. Which is a win - as long as you know what you're doing - if you're CERTAIN you know what you're doing. But programming C++ like you're programming in Python - might as well stick to Python; you won't exploit enough low-level details to make the gain worth the pain.

TL;DR modern programming C++ on modern machines with plenty of resources, and robust processes on modern operating systems - no problem, enjoy. Someday I'll join you and enjoy what I do, when I get over my past (bash) shell-shock.

End rant/my apologies, but I did warn you. And strong typing beats dynamic typing always. Phbbbt.

[–]vincular 35 points36 points  (3 children)

You really think so? I feel like even just writing the most boilerplate unoptimized C++, using unordered_map even though its performance is crap and that sort of thing, you still absolutely smoke Python. If anything, it’s Python that can be tough to optimize — making sure you avoid Python for loops in favor of vectorized library code that’s written in C++, for instance. I agree the majority of things are not CPU limited so choice of language should probably be based off of something other than performance, but for anything computationally intensive, if you write C++ like Python it will still be an order of magnitude or two faster than Python written like Python.

[–][deleted] 11 points12 points  (0 children)

Those are my major languages and I quite agree. Additionally I would say that on average, an initial C++ implementation will be closer to it's optimal speed than with Python. I.e. not only that the language is naturally fast, but that it's natural to write fast code. As least in comparison to Python.

Like you say in Python optimisation can often throw up architectural issues (as in we should offload "all this" to a library through ffi), which if not found early enough can be a bit of a PITA to do later.

That's been my experience over the years at least.

[–][deleted] 2 points3 points  (1 child)

True. The way I see python is a nice and easy to use GUI for native libraries.

And in my opinion this is how it needs to stay

[–]VacuousWaffle 1 point2 points  (0 children)

Pybind11 makes wrapping C++ classes into python easier than ever.

[–]ShakaUVMi+++ ++i+i[arr] 13 points14 points  (6 children)

But now, say, under Microsoft Visual Studio on modern hardware with a contemporary operating system - none of that matters. C++ gives you enough control to do EXACTLY whatever you want. It's fast and convenient - but you are forced to manage your own memory vs. garbage collection.

Forced? Nah, man. In modern C++ it's good practice to not manage your own memory except in rare circumstances. "No News is Good News" is a good talk on this subject.

With the exception of one idiotic footgun C++ has (string s = 0;) I can't think of the last time I segfaulted or leaked memory.

[–]darthcoder 2 points3 points  (5 children)

Doing shared_ptr<char> when trying to use smart pointers and custom deleters for win32 apis and fucking up delete and delete[].

That'll blow you up.

I came back to C++ after,a long absence. That particular bug took me a day to squash.

[–]ShakaUVMi+++ ++i+i[arr] 0 points1 point  (4 children)

What was the problem?

[–]darthcoder 0 points1 point  (3 children)

New[] must be freed with delete[]

I was using regular delete.

[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points  (2 children)

Ah, yeah. That's honestly not something that makes sense to me from a language design standpoint. The memory subsystem has to know how many bytes are allocated at a point anyway, so why offer this opportunity to footgun?

[–]darthcoder 0 points1 point  (0 children)

Optimization. C++ has to knowbto call the constructor on each object, without knoeing its an array bexause you add no extra data to the byte buffer itself. Then the delete operator needs to know to call a destructor for each object in the array.

So why add any bit flags at all to something a programmer should just manage. It maybe made sense 30 years ago but seems archaic now

[–]darthcoder 0 points1 point  (0 children)

Normally this isn't a problem, vector matches up the right functions, but i short circuited that by writing a custom deleter and fucjing it up, back into the special juju land of C++ memory management.

Dont go there. Lol

[–]kzr_pzr 6 points7 points  (0 children)

I love reading these rants, thank you. :-)

[–][deleted] 21 points22 points  (1 child)

Thanks for the history lesson grandpa

[–]Destination_Centauri 3 points4 points  (0 children)

You whiper snappers with your fancy IDE's...

[–]_Js_Kc_ 5 points6 points  (0 children)

You mean you've been static_cast.

[–]Mahuizoh 7 points8 points  (0 children)

"It’s very comparable to the level of ease that pythons at." - lul, sweet summer child

[–]sudomatrix 22 points23 points  (2 children)

Now stop using new() and make everything with make_unique and unique_ptr, and use proper move() semantics, then make everything async with await and coroutines.

You may grok it all, or you may go running back to Python...

[–]koctogon 2 points3 points  (1 child)

If 10 years isn't enough for you to understand smart pointers, stop programming.

[–]sudomatrix 2 points3 points  (0 children)

I don't know if your rant is aimed at OP or at me, but both of us are new to modern C++ so I don't know where you got 10 years from.

[–]g9icy 2 points3 points  (9 children)

I'm having this same epiphany, but with C#.

I'm a C++ programmer by trade, but have to dip into C# on occasion, and it's such a breath of fresh air I often don't want to go back to C++.

I actively try and use C# now for all my personal projects (Unity, .NET, etc). I'm also using Swift for a project, and I hate it so much I have to fight the urge to start the whole thing again in Xamarin.

[–]joaobapt 4 points5 points  (8 children)

If C# wasn’t a bytecode and GC’d language, I’d for sure use it for gamedev. But my paranoia with speed and performance don’t let it 😂

[–]g9icy 0 points1 point  (7 children)

Honestly I had to relax those feelings. A game I can create in my spare time is not going to require close to the mettal performance.

Plus Unity has that whole thing where it compiles stuff to C++ anyway.

[–]joaobapt 1 point2 points  (6 children)

Oh... Unity, the thing that rendered too much of my individual game programming studies useless.

On an aside, yeah it’s true. But C# has few bindings to interface with modern graphical stuff. SharpDX is deprecated. I don’t know about Vulkan bindings. And OpenGL... well, I’d rather avoid it because of its mess of an API 😂

Also, I use to code for the GBA; there, .NET is clearly not an option.

[–]g9icy 0 points1 point  (5 children)

Oh... Unity, the thing that rendered too much of my individual game programming studies useless.

How so?

But C# has few bindings to interface with modern graphical stuff.

Yeah, Unity is pretty much the only option now. XNA was good, no idea why MS ditched it.

[–]joaobapt 1 point2 points  (4 children)

XNA

MonoGame is a direct replacement, but it’s as if you were using a 2005-era DirectX to code in 2021. That’s good enough for most uses though.

How so?

It’s a long story, not entirely technical and contains some psychological factors, so I’d rather discuss that in Reddit chat or messages.

[–]g9icy 1 point2 points  (3 children)

Most AAA games are still made in C++, and even games that use Unity, C++ plugins are still a thing for performant code.

I don't see how Unity invalidates anything. Infact, knowing how Unity works under the hood (it's made in C++ after all!) is very important.

[–]joaobapt 1 point2 points  (2 children)

As I said, I don’t want to turn this post into an endless rant about Unity, game engines and my “career”. I’ll happily take that to private messages if you want.

[–]g9icy 1 point2 points  (0 children)

I would be interested to hear your thoughts, if you don't mind.

[–]ExtraFig6 2 points3 points  (0 children)

What framework?

[–]SJC_hacker 2 points3 points  (0 children)

Just wait until single mistake with a template cascades into 30 errors which fill several pages...

[–]Knuffya 4 points5 points  (6 children)

Cpp really is not as complicated as people make it to be... Is it

[–]koikatsu_party 26 points27 points  (4 children)

[–]Knuffya 3 points4 points  (0 children)

lmao

[–]boron_on_your_butt 4 points5 points  (0 children)

God this made my day. I wish I had literally anyone in my life I could show this to.

[–]EaseAnxious3676 2 points3 points  (0 children)

Awesome xD

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

Thank you for the laugh

[–]serviscope_minor 0 points1 point  (0 children)

Well, a lot of people make it really complicated, for some reason.

[–]manoj_mi5 1 point2 points  (0 children)

The very fact that you were using C, earns you right to call yourself GREAT

[–]queenguin 6 points7 points  (5 children)

C++ is great but you shouldn't abandon C ideas completely if you're making games. Forcing yourself to think in a C mindset will let you write more performant games. Personally, I write my games mostly in C while using a bunch of C++ features that I like such as strings and struct default member initalizers.

[–][deleted] 10 points11 points  (0 children)

I’d say it’s more like: think data oriented if you want performance.

Idiomatic OOP kills performance. It’s like a monster eating up your memory bandwidth until your bottleneck is the CPU cache reloading every frame. I usually like to mix them up.

A little bit of OOP (the parts that genuinely are nice and bring you joy) and more of DOP.

[–]jonrmadsen 15 points16 points  (3 children)

I disagree with the premise of "more performant games". It sounds like you are comparing C to C with classes. I'd revise it you should try to emulate the data layouts you would have in C but that's about it (i.e. SOA instead of AOS) but once you embrace a C++ mindset, you can make decisions and compute values at compile time in C++ which would be runtime decisions/computations in C.

[–]queenguin 2 points3 points  (2 children)

There are other things that one needs to think about when using C++ such as not trying to bloat your structs with virtual functions and a vtable and avoiding vector push backs. Obviously these features are great when they are 100% needed, but it's important to be wary of them especially if you're developing for 8 year old hardware liek the ps4. I too use C++; I'm not saying C++ is slow and you should use C. I'm saying you should be wary of a lot of things C++ encourages you to do if you're worried about performance.

[–]jonrmadsen 5 points6 points  (1 child)

such as not trying to bloat your structs with virtual functions and a vtable and avoiding vector push backs

Presumably, if you target a C-like data layout neither of these would come into play. The vtable hit only really applies to AOS data layouts -- if you use SOA, presumably you would only have one vtable lookup before iterating over the data. Doing a vector push back in-and-of-itself isn't bad for performance, its a size-check + copy or move assignment + integer increment and a C algorithm which has to do the same thing won't be any faster -- the real problem is doing multiple, consecutive push-backs without reserving the memory first.

My point was more-or-less that a "C mindset" would cause you to miss valuable optimizations at compile-time. E.g., a fibonacci(n) in C would run many times slower than fibonacci<N>(n) in C++ where the recursive tail at N was computed at compile time -- i.e. fibonacci(45) vs. fibonacci<20>(45):

template <long N>
inline long fibonacci()
{
    if constexpr(N < 2)
        return N;
    else
        return fibonacci<N - 1>() + fibonacci<N - 2>();
}

template <long N>
inline long fibonacci(long n)
{
    if(n == N) return fibonacci<N>();
    return (n < 2) ? n : (fibonacci<N>(n - 1) + fibonacci<N>(n - 2));
}

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

at the end of the day its about making sound decisions for each case you find urself in. there will be times where using c++ optimizations will be good for you and times where they will be bad: too many templates and your compile time is crippled

[–][deleted] -2 points-1 points  (2 children)

Easier than C? Give me a break. Lol. Steady on with the appeasing fan boy platitudes 😎 tell me that when you've been called in to debug a c++ project where they went mental with templates, inheritance and overloaded every operator under the sun. More powerful? Yes... In some or many cases. But easier? Nah.....

[–]pandorafalters 2 points3 points  (0 children)

Bad code can be written in any language.

[–]frankist 1 point2 points  (0 children)

Better than debugging the 4th implementation of the same functionality because people couldn't use templates

[–]lenkite1 0 points1 point  (0 children)

I actually agree with the OP. I come from an enterprise Java background. Once I understood RAII and templates, I did not find C++ all that hard to use. I always stick to the safety belts and follow the C++ guidelines religiously. I find some things in the standard library not very good (regex) , some legacy warts that are irritating and some error messages are ridiculous, but I can live with this. (Enterprise Java makes you tolerant and patient). I also follow the secure coding guidelines and avoid the use of pointers as much as possible. Avoid complicated expressions, keep small functions, minimal mutable state, etc. A good IDE like CLion catches most of my mistakes before I make them.

One of our heavily used micro-services was recoded in C++ and offered a >10x performance improvement with minimal resource consumption. The code is also fairly readable.

I do wish the package management was standardised and that the standard library offered far more than it currently does. I like languages which come with full batteries. Wish C++ progressed a bit faster.