> informatique > prog > cpp > grammar > move-semantics-and-special-members-howard-hinnant

Engineering Distinguished Speaker Series: Howard Hinnant

Inside Bloomberg - 2016-09-19

Howard Hinnant spoke at Bloomberg presenting everything you need to know about move semantics.

For Engineering jobs http://bit.ly/23gXZzd

Andrea Bigagli - 2017-01-15

One of my favorite C++ talks from one of the clearest and most respectable speakers out there. I actually went further and just made that wonderful "special members" table my laptop's wallpaper, and that was more than 1 year ago when I first found those slides (can't remember exactly where, maybe on Howard's website?). Now, if only Howard could give a talk on perfect forwarding, I'd probably find another permanent wallpaper for my external display... ;-)

Ryan Cuthbertson - 2018-08-03

The slides are found at http://howardhinnant.github.io/bloomberg_2016.pdf

Ed - 2020-04-17

A beginner question here: if 42:16 you default everything then wouldn't the compiler be generating everything for you which means you would be dealing with a shallow copy issue here, assuming your class manages resource which in this case I found odd that the class example in the slide had a std::vector and not T*.
PS: someone gave me the link to this presentation from a question from CodeReview where I implement a std::vector-like vector https://codereview.stackexchange.com/questions/240457/stdvector-implementation-c, to watch the presentation specifically where the talk about copy and swap that begins in 35:27

Howard Hinnant - 2020-06-21

At that point I'm defaulting the special member functions for class X, which in turn call the non-defaulted special member functions of std::vector. The vector copy members will not do a shallow copy.

Sanjiv Gupta - 2018-06-27

In my 20 years old career I have had never seen a time when C++ was debated and discussed so much. The reason is very clear: C++ never had been so confusing . So I am just wondering if the language is getting better or worse?

Peter Sobieraj - 2020-07-15

Move constructor is not that bad. I have look at few examples and I think I understand it.
But lambda functions, and few other things are not.
Lambda function is simple concept, but C++ syntax is so crazy that I just don't use it.
But (2) I guess the reason for that crazy syntax is to make C++ as backward compatible as possible.
And for me it's woth the cost.
I use to work as PHP developer, and once pre few months I had to go thru all the projects, and rewrite bunch of code, just becase there was a new PHP version, and old code didn't work any more.

eRCaGuy - 2020-09-13

I find C++ to be a **monster of a language**. I speak English, Spanish, a good deal of French, some Portuguese, and a tiny bit of Arabic, and when I look at C++ I'm mind-boggled: it's as though C was Spanish, and C++ decided to be English, Spanish, French, German, Italian, and Portuguese all rolled up into one! It's mind boggling. I call it, "the language that just keeps on giving." Nevertheless, I use it every day now and am still forming my opinions about it. I come from embedded C and "C+" (using C++ compiler to do basically low-level C-like code, but with C++ classes, struct member initialization with default values, etc.). Anyway, I'm still forming an opinion, but it's incredibly discouraging sometimes looking at C++ code I'm trying to understand, modify, and add to, and I very frequently find myself thinking, "do these people really think this is a good idea!!!? How the heck did they get into this mess!?" I think it all stems from the (bad) notion of trying to make everything its own type in order to protect the programmer from him/herself. I think this is a bad way to go. I find the beauty and simplicity of C plus basic C++ to be phenomenal, and the severe complexity of full-blown modern C++ to be...discouraging and frightful. Nevertheless, like I said, I'm using more and more of its advanced features every single day, and still forming an opinion.
Today, I used `std::optional::emplace()` for the first time to copy-construct an instance of a class into a fixed statically-allocated memory location, when in C or basic C++ I'd have just used `memcpy()` and been done in like 10 minutes! In advanced C++, it's taken me ~30 hrs over 3 weeks instead. Why? Because the class is not trivially copyable: one feature in C++ in the name of type safety led to another limitation led to another feature led to another limitation lead to 5 more features and 5 more limitations until I find myself locked inside this narrow box with only a few obscure and complicated solutions, `std::optional::emplace()` being the easiest of them all. But: why such a narrow opening to exit the box? Type safety: the false mentality of the C++ programmer that everything has to be an object, instead of just using procedural programming where it makes sense, and that everything has to be a unique type, instead of just letting the programmer be a good programmer. We have tied our hands too much when one uses all of C++'s features, but: I have no choice. That's the code base I am in. So, I will learn. I will take notice. I will get good at it regardless. But, I will try to form a sound opinion and make better decisions in the end.
See also my other comment here: https://www.youtube.com/watch?v=vLinb2fgkHk&lc=Ugy4MvBZcqO-AtYXa9R4AaABAg.

heyheyhophop - 2020-12-19

OK, so while at 18:56 -- how does one reason about the case when both the default ctor and dtor are declared by the user?
Are move ctor and move ass-t defaulted or not declared?

(the same question applies to other possible combinations of user-declared special functions)

Howard Hinnant - 2020-12-21

You can think of "not declared" or "deleted" as "stronger" than "defaulted". So when the table seems to imply a possibility of either, due to multiple members being user-declared, the stronger wins.

Specifically in your example, when both the default ctor and the dtor are declared by the user, both copy members are defaulted, and the move members are not declared. Furthermore the behavior of the compiler defaulting the copy members is deprecated and you may get a warning to that effect (red squares indicate deprecated behavior).

홍홍 - 2021-12-01

@Howard Hinnant 19:20 deprecated means that they will be implicitly declared but defined as deleted? Or they will be not declared at all?

Howard Hinnant - 2021-12-01

@홍홍 When the destructor is user declared the copy members are implicitly defaulted. This may produce a "deprecated" warning. The future behavior has not been defined yet by the committee. Indeed, since the deprecation has lasted a decade now, I'm beginning to think that this behavior will never be removed, and might even be un-deprecated in the future.

Alexey Kuzmin - 2016-12-08

Why isn't a destructor deprecated when the copy operator/constructor is user-defined?

Howard Hinnant - 2016-12-29

I don't think this was ever considered. Here are the relevant papers that would have all of the rationale:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3174.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3201.pdf

Francis Rammeloo - 2017-01-19

What about `Item(const Item&&);` Is there ever a reason to implement it? What is it's semantic meaning?

Andrew Jewell - 2017-01-25

Why wouldn't non-const work just as well? It's the "=delete" that does the magic, right? What am I missing?

Jared Mulconry - 2017-01-26

There are situations where the temporary may be a constant, in which case it wouldn't bind to a non-const version. const r-value reference is a catch-all for temporary objects.
When you declare the function and mark it '= delete', it will participate in overload resolution and, if chosen, will produce a compile-time error. If you didn't declare the function, then it wouldn't participate in overload resolution and some other overload may be chosen instead. 'const T&', for compatibility reasons, is a very sticky parameter type. 'const T&&' is the most effective way of catching all temporaries.

Andrew Jewell - 2017-01-26

Can you give me an example of where the temporary is a constant? I've not been able to find or create an example that binds to a "const T&&" but not to a "T&&".

Howard Hinnant - 2017-01-26

If you have a function that returns a `std::string const` by value, when called, that generates a const temporary (prvalue) std::string. Such an argument could never bind to `std::string&&`, but will bind to `std::string const&&`. If there is both a `std::string const&` and a `std::string const&&` in the overload set, lvalues will prefer the former and rvalues will prefer the latter.

Andrew Jewell - 2017-01-26

I understand now. Thanks.

홍홍 - 2021-10-22

28:46 helpful

Carl Schumann - 2022-11-19

13:20 Special members table presentation