Live data from Hacker News

Move in C++ without a std:move

andreasfertig.com

41–50 of 75 posts

Re: Move in C++ without a std:move

#41

- stupid question, since we are on the topic of c++, i finished reading through learncpp.com - how do I take this from 0 to the guy that builds a play station 3 emulator? - like seriously what kind of step by step projects or learning experiences in increasing order of difficulty do you recommend to get really really good at c++

You don’t need to be really good at cpp to write a crappy emulator. All the “really good” stuff is about eeking out performance. If you want to build an emulator start with a qt gui and go from there. By the time you’re done you’ll be good enough

Re: Move in C++ without a std:move

#42

- stupid question, since we are on the topic of c++, i finished reading through learncpp.com - how do I take this from 0 to the guy that builds a play station 3 emulator? - like seriously what kind of step by step projects or learning experiences in increasing order of difficulty do you recommend to get really really good at c++

The fun thing about C++ is that it’s really hard. The even more fun thing is that the domain knowledge behind is even harder - game engines, high performance clusters, emulators, real time simulations, rendering engines, high frequency trading - so more often than not most C++ devs commit to learning a language subset and then focus their energy on the task at hand. A PS3 emulator might be a switch statement (not really, but you get the point)

Re: Move in C++ without a std:move

#43

- stupid question, since we are on the topic of c++, i finished reading through learncpp.com - how do I take this from 0 to the guy that builds a play station 3 emulator? - like seriously what kind of step by step projects or learning experiences in increasing order of difficulty do you recommend to get really really good at c++

Getting very good at C++ takes more than a decade. There are no shortcuts. You will have to start by getting in the trenches and write some code.

> ... and write some code.

This but replace some with more. Write more code! Programming is like any other discipline which requires constant training and exercise. Doesn't matter if its Jujutsu or C++, you must train and become well versed in all the aspects of the craft.

Re: Move in C++ without a std:move

#44
post #33
post #10

Earlier quoted context omitted.

The simple cases are simple. However the complex cases get hard. mytype foo() { mytype one; ... if(something) { mytype two; ... return two; } return one; } Is going to be much harder because you don't know are compile time which is returned and so cannot construct the one you return in the correct place. That is just off the top of my head, I'm not a compiler writer, I'm sure they have figured out the simple versions…

That one is not too hard either. `one` simply can't be NRVO'd as there is a runtime path in scope of it that doesn't return it. `two` can be (unless you hide some other return within ...).

You can structre the code differently to get around that. There is a real desire to use NRVO "one" in cases when it is returned as well, if possible.

Re: Move in C++ without a std:move

#45
post #8

Earlier quoted context omitted.

This is one case where Rust benefited from C++’s experience — move by default with opt-in clone/copy is IMO the better setup.

And the most important idea: destructive moves. Since C++ doesn't track lifetimes it has to leave the object in a "valid state" after a move and the destructor still runs which has to have a check if it should do something or not.

While not the common case, C++ move semantics match the situation in systems code where correctness requires decoupling logical object lifetimes and destructors. The object is logically dead but the destructor may be deferred indefinitely for safety reasons.

Most code doesn't have the shared memory setups where deferred destruction is necessary.

Re: Move in C++ without a std:move

#46

What is that makes NVRO so much more difficult to implement? Why couldn't they mandate that just like RVO? Do compilers literally just special case a simple return statement of a direct construction or something?

The problem is that "predictable reliable NRVO" is still a research problem. Real-world compilers do NRVO a lot but not in a way that is perfectly predictable — that is to say, not in a way that could be standardized across all compilers (or even between different releases of the same compiler).

A "perfectly predictable" algorithm was proposed in Anton Zhilin's P2025, back in the year 2021: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p20... but unfortunately it had some subtle corner-case problems (which I do not remember), so it was sent back for revision, and never returned with a fix. (Maybe because a fix wasn't possible; again I don't remember what the deal was exactly.)

The Right Path Forward would be for MSVC, GCC, and Clang all to try implementing P2025's algorithm in their front ends. Either something concrete breaks (reminding me what the problem was), or else all three mainstream compilers gain predictable NRVO and then we can "standardize existing practice." But the Right Path Forward requires tedious work by at least three people, which is hard.

Re: Move in C++ without a std:move

#47

- stupid question, since we are on the topic of c++, i finished reading through learncpp.com - how do I take this from 0 to the guy that builds a play station 3 emulator? - like seriously what kind of step by step projects or learning experiences in increasing order of difficulty do you recommend to get really really good at c++

I would recommend reconsidering the "PS3" part. I had to revisit a codebase that supported the beast more than a decade ago recently, and I was in shock at how weird the PS3 bits were. As for "really good", I would dodge that since I have only been using C++ for like 25 years =)

Re: Move in C++ without a std:move

#48
post #19

Earlier quoted context omitted.

Yes, it works exactly like this, this is a demo on godbolt [0]. rdi stores the pointer in both cases, makeS1() uses RVO, makeS2() takes it explicitly and constructs with placement new. I will say before testing this i didn't realize the RVO calling convention was to return the pointer you pass in, but apparently so. If makeS2() returned void, it's just a tail call to the constructor, but makeS1() has to spill rbx and…

No, all you're showing in that example is that a pointer is passed as part of the ABI. You're not showing that RVO relates to that in any way whatsoever. If you write the same function in a manner that (N)RVO can't kick in, does the pointer no longer get passed? The reason this should sound dubious is that you're suggesting the caller needs to know the callee's body in order to know how to call it, but it should be p…

Fair enough, I don't know the C++ ABI to this extent.

Re: Move in C++ without a std:move

#49

Unfortunately, I don't think there's getting away from just understanding value semantics to get the correct and/or performant behavior.

> Unfortunately, I don't think there's getting away from just understanding value semantics to get the correct and/or performant behavior.

This is not specific to C++ though. It just so happens that C++ developers who feel this topic is important are those invested in performance optimization. For them, C++ offers them these types of tools.

Meanwhile, those who don't have a pressing need to go through great extents to optimize performance can simply fall back to the compiler generating most special member functions and then pay the performance tax of doing deep copies by default. For these cases, which I'd say corresponds to most C++ floating around, it's far more important to know the rules of when to define our own custom constructors and assignment operators.

Re: Move in C++ without a std:move

#50

Earlier quoted context omitted.

Despite its name, NRVO isn't an optimization performed by the optimizer, it's something done by the frontend of the compiler before it generates the code for the optimizer to run on. The frontend is extremely reluctant to do anything like flow analysis, in large part because the frontend doesn't even really have any code to do the analysis on, just the AST. More people (including far too many on the committee itself)…

They probably _were_, since lower level code representations often has little notion of complex types and their semantics they could be kept clean and focused on machine code, however type inference in a language like C++ complicates such matters immensly since an assignment can be both a register move and a function call. Template resolution solved that in the past, but C++ today allows auto in so many places that I…

> Template resolution solved that in the past, but C++ today allows auto in so many places that I'm uncertain that it can be done without some flow based support (if constexpr comes to mind).

This concern is unfounded. The auto keyword in C++ acts as mere syntactic sugar. It works only when the compiler is able to tell exactly what's the type by evaluating the expression.

The auto keyword is also considered a code smell for the same reason: just because the compiler can tell exactly what the type is expected to be, that does not mean the developer can. Therefore it makes the code harder to reason about.

Post reply on HN