Maxatar 1 day ago

I'm not familiar with programming languages that generate redundant stores in order to initialize anything.

Usually what happens is the language requires you to initialize the variable before it's read for the first time, but this doesn't have to be at the point of declaration. Like in Java you can declare a variable, do other stuff, and then initialize it later... so long as you initialize it before reading from it.

Note that in C++, reading from a variable before writing to it is undefined behavior, so it's not particularly clear what benefit you're getting from this.

3
josefx 1 day ago

> Note that in C++, reading from a variable before writing to it is undefined behavior, so it's not particularly clear what benefit you're getting from this.

The compiler cannot always tell if a variable will be written to before it is accessed. if you have a 100kb network buffer and you call int read = opaque_read(buffer); the compiler cannot tell how much or if anything at all was written to buffer and how size relates to it, it would be forced to initialize every byte in it to zero. A programmer can read the API docs, see that only the first read bytes are valid and use the buffer without ever touching anything uninitialized. Now add in that you can pass mutable pointers and references to nearly anything in C++ and the compiler has a much harder time to tell if it has to initialize arguments passed to functions or if the function is doing the initialization for it.

tialaramex 1 day ago

In C++ 26 you will be able to specifically mark that you want the initialization not to happen, whereupon of course (a) your reviewers can see this and critique it, are you sure it doesn't need initializing? Isn't this the code we run once per month that doesn't need to be fast or small? (b) the maintenance programmer coming later can identify that you did it on purpose and consider whether it's still correct

The problem was never "This is always a bad idea" and instead only "This is usually a bad idea so you should need to explicitly ask for it when you want it, so that when somebody writes it by mistake they can be told about that".

Rust chooses to need a lot of ceremony to make a MaybeUninit, and especially to then assume_init with no justification because it's not actually initialized - but that's because almost nobody who wants to write that understands what will actually happen, they typically have the C programmer "All the world's a PDP-11" understanding and in that world this operation has well understood and maybe even desirable behaviour. We do not live in that world, this is not a PDP-11 and it isn't shy about that. The thing they want is called a "freeze semantic" and it's difficult to ensure on modern systems.

But if you hate the ceremony, regardless of the fact there's a good reason for it - many languages have less ceremony, often just a handful of keystrokes to say "Don't initialize this" will be enough to achieve what you intended. What they don't do, which C++ did, was just assume the fact you forgot to write an initializer means you want the consequences - when in reality it usually means you're just human and make mistakes.

zahlman 1 day ago

> Note that in C++, reading from a variable before writing to it is undefined behavior, so it's not particularly clear what benefit you're getting from this.

You gain the benefit that the compiler can assume the code path in question is impossible to reach, even if there's an obvious way to reach it. To my understanding, this can theoretically back-propagate all the way to `main()` and make the entire program a no-op.

tialaramex 1 day ago

There are real (in the sense they compile in actual C++ compilers people use and the resulting executable will run) toy (ie not intended for production use) examples where you can cause the compiler to conclude that executing this never-called function named format_hard_disk or begin_world_war_iii or whatever is the only remaining possible meaning of the program so that's what happens when it's run.

Nobody has written an actual format-hard-disk or start-world-war-III routine, because we're not crazy, but the alarming function naming is intended to signal what a terrible idea it is to have this programming language at all.

jorhannn 1 day ago

>Note that in C++, reading from a variable before writing to it is undefined behavior

They are finally fixing that in C++26 where it's no longer undefined behavior, it's "erroneous behavior" which will require a diagnostic and it has to have some value and compilers aren't allowed to break your code anymore.

tialaramex 1 day ago

But the price for that is indeed those "redundant stores" which it appears today C++ programmers are convinced explain the slowdown.

I mean sure, the real cause is more likely their incompetent use of the wrong algorithms and data structures or the fact that it's too hard to rely on external dependencies so they're still using a stdlib feature that's known to be significantly slower than the best efforts but eh, it's just a single #include away.

jeffbee 1 day ago

Redundant stores are not some kind of myth. People spent a long time reducing redundant stores in the constructors of the protobuf library, for example, and this has measurable efficiency benefits.

tialaramex 1 day ago

They aren't a myth, but they're very easy to overestimate as a cause of problems.

jeffbee 23 hours ago

Granted. Be guided by profiles, always.