Comment by jb1991
7 years ago
> the added features can not remove complexity, they can just add to it
There are countless examples of the so-called modern C++ features reducing complexity in code.
For example, it is now considered a code smell to ever write "new" or "delete" in your code. Imagine that, never using these words to manually allocate and delete memory in C++! But it's true, unique_ptr in particular makes so much simpler and safer.
Type inference with auto doesn't just save typing, it improves performance in many cases and reduces a lot of complexity, while also avoiding uninitialized variables.
These are just a few of at least a dozen examples that come to mind about reducing code complexity with more modern C++ features.
New features can reduce the complexity of code, but they cannot reduce the complexity of the language.
C++ programmers still need to know what "new" and "delete" do, so they can work with older code that uses them. They also need to learn what "auto" does, so they can work with newer code that uses it. (The behavior of "auto" isn't trivial; how many C++ programmers understand the difference between "auto v = <expr>;" and "decltype(<expr>) v = <expr>;"?)
Why would you ever use or see the latter? Fabricated examples aren't helpful.
You wouldn't...
...instead you'd use "decltype(auto) v = <expr>", which is equivalent. And people certainly use decltype(auto), or else it wouldn't have been added to the language, 3 years after regular auto.
Not sure why this was downvoted, decltype was introduced with C++11 alongside of auto for declarations: the example given isn't accurate of reality. A better one might be a function returning auto vs returning decltype(some expression).
6 replies →
I hate unique_ptr and shared_ptr, using them is so glaringly inconsistent. Half the time you can’t construct a unique_ptr when it’s easy, because you don’t have the information until just enough later (like after a calculation or two in the body of your constructor) that you can’t use the easy way. So how do you transfer a unique_ptr? Well, the obvious ways don’t compile, and you eventually learn you have to move it, which involves using std::move(), but it always seems to go in the place I don’t expect it. And then how do you use a unique_ptr outside of your class? You can’t pass by value, for obvious reasons. Pass by reference, maybe? I think that’s frowned upon, I think you’re supposed to pass a naked pointer, and Modern C++ code is supposed to understand that naked pointers mean I’m loaning you this pointer. But I thought the point of Modern C++ was to get rid of pointers? Anyway, shared_ptr works completely the opposite way. You are supposed to pass the pointer by value. Now you can argue that of course it’s supposed to be that way, and the arguments are all cogent and when you spend half a day figuring it all out it makes sense. Until tomorrow when you forget it all and have to actually use the things. Plus I hate underscores with a passion, it hurts to type them. Modern C++ also seems to like making a line of code longer and longer, because you can’t just make a unique_ptr or shared_ptr with a constructor, no, you need make_unique<typename>(...), and the arguments are magically the same as the type’s constructor, even though it’s obviously a different function. Yuck! At least new and delete are pretty obvious how to use, and only have one special case to worry about ([]). Granted, the *_ptr are better, but I hate using them and wish I could use something that was shorter and easier to remember.
> I hate unique_ptr and shared_ptr, using them is so glaringly inconsistent.'
They're glaringly inconsistent because they behave differently with regards to ownership, and the fact that you can't copy them or pass them around in certain cases is because they're designed to stop you from doing this as it would undermine the reason you're using the class.
Yes, but that fact is I can't ever remember how to use them properly (unique_ptr in particular). It's not often that you need to pass a unique_ptr to a function outside your class so that it can do something with it (without transferring ownership), so I can never remember how I'm supposed to do it. But it seems like if I want to hand a pointer to a short-lived function, doing it ought to be pretty consistent, whether I'm passing an old-skool naked pointer, a unique_ptr, or a shared_ptr, and it's not.
Like I said, if you look at all the logic, there's a good reason why everything is the way it is. The problem is I can't use the things without looking them up. Usability of my language is a big deal for me, which is why I hate unique_ptr.
FYI, you can use a constructor with a shared/unique ptr.
auto p = unique_ptr<Foo>(new Foo());
Totally works, and may be easier to remember if you dont like the "magic" parameter forwarding.
Careful with that if it's not the only thing happening in the statement. It might be a while between the 'new' and the unique_ptr ctor. If an exception happens in between the object will leak.
e.g. foo(unique_ptr<X>(new X), unique_ptr<Y>(new Y)) is a leak waiting to happen.
https://stackoverflow.com/questions/37514509/advantages-of-u...
2 replies →
The vast majority of the time you just want to pass a reference to the pointed-to object (for both unique_ptr and shared_ptr). Once you've decided what you're actually going to do with the object, that usually determines how you're going to want to pass it.
> But I thought the point of Modern C++ was to get rid of pointers?
no it's not, it never has been. The point of modern C++ is to get rid of owning pointers.
How does auto improve performance? Doesn't it just expand to whatever type a human would have manually had to put there in the first place?
It allows automatic generic specialization in some cases by the compiler, as you don't have to do template-fu or use a nonspecific type or manually write multiple specializations.
Plus it usually makes the code cleaner by focusing on structure not types. As any construct, it can of course be abused.