And in the followup, they assume the candidate will just assume that "SearchQuery", whose header is not shown, will have a copy constructor.
Just no.
And in the followup, they assume the candidate will just assume that "SearchQuery", whose header is not shown, will have a copy constructor.
Just no.
However, understanding that SearchQuery is broken is pretty important. Breaking the Rule-of-3 is probably the #1 mistake made by junior C++ developers trying to write object-oriented code, and the consequences are pretty nasty. You'll get corruption and crashes from use-after-free and double-free errors and nothing will make sense because the problem will move around as you create temporary copies while trying to debug.
That being said, I wasn't familiar with that sort of stuff when I was first hired as a C++ developer. I was very fortunate to start my career with a company that was willing to hire people and train them.
I'm pretty sure business do not like to actually train people nowadays. :)
It's now called the rule of 5.
RAII basically assumes that your objects are always going to be in the init-use-free pattern (you read a file, you use it, and close it after you’re finished) In reality not all things work this way, as objects have various different states according to their state machines and will use and free resources depending on that state. But in Modern C++ you’re forced to think only in the on/off paradigm, which results in lots of small unnecessary classes with their own on/off state. (If you try graphics programming you’ll understand right away...) Now when you add rule-of-five this becomes a monstrosity to handle, as you have to ensure about memory copying/moving for every little RAII class you make.
So why not let normal assignment be shallow copy by default, but have an explicit copy() method? Why is everything so implicit in Modern C++ where you can’t assure that by simply looking at a = b you can’t tell how memory is allocated/freed...
Nowadays I have lost hope in Modern C++ and are looking for alternatives: Rust (complex but at least memory safe) Orthodox C++ (not memory safe but at least sane for graphics/game programming), or Jai/Zig/other experimental lnguages (which claim to be a better C)
You could say, "well, developers can just adopt a uniform semantics for what parts of objects are considered 'shallow' vs. 'deep'", but now the compiler can generate correct default copy operations in many fewer cases, since the rule is arbitrary vs. simply "copy everything".
You're right that the RAII model sometimes feels a bit limiting for the complexity sometimes found in graphics, but I think part of that was self-inflected by our API design. That seems to be changing. The best-looking technique I've seen for handling Vulkan/DX12 is to make your program more like a compiler. You take a scene as input and you compile it into a command buffer to give the GPU. Your resource handling for stuff like texture slots thus looks more like register allocation. State shadowing is a trivial optimization pass when your GPU code is data.
The problem is that when you write RAII classes for GPU resources in the traditional way, C++ sees the GPU state through a tiny pinhole and thus can't optimize very well. When you treat your GPU commands as a program that your C++ program is building, you have more global information about GPU state available, which allows you to make more efficient choices.
For example, it's trivial to have shallow copies by default - just wrap it in std::shared_ptr (or a thread-unsafe homebrew version if you can prove that synchronization is a performance problem).
I admit to not having done a lot of graphics programming, but I can't shake the feeling that you are using modern C++ wrong if your complaint is "too many small RAII classes".
No, it really isn't. The whole point of a unique pointer is to ensure that the pointer is in fact unique. Thus, std::unique_ptr is specifically designed to disallow any form of copying.
This is not minutae. This is a test if you understand the theory behind ownership semantics.
No.
Those utilities weren't standardized before C++11. People wrote their own implementations before that. People had to understand stack unwinding and scoping, memory, RAII, design patterns that relate to allocation/de-allocation of memory, ownership transfer.
Then came in the people that decided it'd be a great idea to start quizzing others about C++11 concretions.
So it has been almost a decade. How much longer before the whole move semantics addition to the language specification becomes relevant to you?
As a veteran of three decades of C++, I've seen a lot of new hotness turn into old and busted and removed. There's plenty of dark corners where you don't need to look to get a job done.
I'm not debating the usefulness of move semantics. I'm debating the weight being placed on them in these so-called "C++ interview questions". Wouldn't it be better to discuss the actual problem, rather than a concrete solution we ended up having in C++11?
That's quite a disigenuous statement. Work on C++11 started after the approval of c++98, and the c++0x smart pointers have been implemented and available for quite a while before C++11 was finalized.