20:56 Jason, if your audience can’t even ask questions about what you just said it is not the audience fault, it is the instructor’s. For me a successful lesson is when I have been so clear that everyone understood.
I like watching these videos and keep coming Empty handed in terms of what I have learned at the end. It is possibly related to the flaky/fluidic/all-over-the-place opinion polls which he keeps taking.
26:30 On both gcc and clang only aggregate initialization extends lifetime. Additionally gcc is smart enough to notice this and warns about unused variable only if it does not extend lifetime of object with destructor with side effects.
Yes, I think Jason got this wrong. The reason is that if you use a constructor, then the member initialization is from a constructor argument not from a temporary, and hence it won't extend the lifetime of the temporary you pass to the constructor.
I think that vacuous is a term used to describe a data that is destructible or supportive to confined randomization, which are options of the programmer.
"If you know who I am and have seen my previous talks, you may want to move to the front" I would have done that and yelled wrong or right answers because Jason reaction will be fun
43:45 "that is not the opening curly for main" That's because that was put at the end of the previous line so it's easily overlooked. And that's why I've always been in the "put the curly on the next line"-camp. Apart from visual separation of multi-line parameter lists and the function body.
I just tried the std::string_view returning function with a const char[] local array. GCC (pre-12 trunk) now warns against this (with a cryptic error message) __only in O3 mode__. (it prints garbage/nothing when using any other optimization level). CLang (pre-14 trunk) compiles fine and does print "hello world" __only from O1 and up__, it still prints garbage for O0 (but never warns). I find it strange that compilers are still not able to detect "local variable use outside function" UB.
Const ref lifetime extensions make me uncomfortable. I would rather just get a compiler error if I try to take a reference of an rvalue, imho. The fact that "const T &x = getRValueT();" is valid and compiles without error makes me so uneasy. This feature seems more like a hack to protect silly mistakes where a compiler error (or even just a warning) should have been enforced instead. The destruction of a reference should never trigger a destructor :\
Blake Scherschel That exists for backwards compatability with temporary Lifetime Extensions from before the days of &&. It basically allowed you to construct a T from and rvalue pre C++11.
It's useful in generic code. It lets you use auto const &x = (expr); or auto &&x = (expr); to bind the expression to an identifier without having to know whether expr is a glvalue or a prvalue.
It allows you to pass a temporary to a function that accepts a const reference. And we all do that all the time, so this feature is not obscure by any means. void foo(const Bar& bar) { ... } foo(Bar());
48:36 If I were to do something with s and get_Holder().s seperately before returning it can't move right? Because you're technically using both objects? I'm I correct in my understanding that it will only do this if it knows it CAN be moved at all (ie. you're not using the moved-from object anymore before returning)?
Inside get_Data, you can't do anything with s until it's initialised. It's initialised from get_Holder().s, which is the only usage of that. You can use s as much as you like after that, until it's returned -- afterwards of course you can't do anything with it since you've returned. None of this changes the pattern of calls. You can't use "get_Holder().s" *again* without either calling it again (which is a separate usage that will make the same calls again) or just using s, since that's a local (moved) copy of the same object anyway.
When C++11 hit the scene that rekindled my interest in C++ and I went and wrote a significant amount of C++11 for a special project. But even as new and cooler things are being added to C++11 to get us to C++20, videos such as this one are demoralizing my interest in staying with C++ going forward. I've now watched several Cppcon 2018 videos and nearly everyone of them was something on the perils of C++ if you don't understand it to an arcane level. (Two exceptions was on C++ for Nividia GPUs and a cool one on template engine to parse regular expressions at compile time - and even evaluate them.) A new book appeared this year The Rust Programming Language. I've been going through it and am seeing that it's possible for a rank and file programmer to actually master the breadth of the Rust language. With C++20, Concepts will, yeah, make it easier on rank and file programmers to consume template classes and compose somewhat simple template classes themselves, but to really master C++ generic programming just ballooned another order of magnitude in breadth complexity (and it was already exceedingly arcane). All the special case gotchas and surprising behaviors of the C++ language just further demoralize. There are so many special knowledge issues to track and keep up with. A programming language really shouldn't have this much cognitive baggage overhead. It really does prove the case that their needed to be a fresh start on a new systems programming capable language and thus far Rust is the best candidate for that.
To some extent, it is also that C++ developers love to focus on these cases, and to some extent also love to play in the language approaching the corner cases. I recently encountered a devastating performance bug in a Java application. One of the dependencies were using WeakReference when they really probably meant SoftReference. That, in turn, caused total performance havok under specific loads with a subset of JVM versions. In fact, coming from a C++ mindset might have made it easier for me to spot this. The team had already isolated the method were this was done as the bottleneck, but they didn't have the "object liftetime" mental alarm firing off.
@@-taz- to be a true systems programming language and that could be used in embedded programming, it needs to be a language that does not have a complex runtime requirement - that rules out all the garbage collection memory management languages. golang is a good language and is very simple language, by relative comparison to many others, and it's good for a certain species of quasi systems programming - the Docker daemon being most famous example. Golang sweet spot is services and tools - especially quickly developed custom tools. But golang uses garbage collection memory management and has a substantial runtime - it doesn't qualify as a systems programming language in the vein of C, C++, D, or Rust.
@@carlnettelblad1139 I work on my C++11 code base project on an intermittent basis (a few weeks go by and then I go dive back in to add new feature, etc). I often grab my Scott Meyer book and go re-read sections of it to get my head back into best practices guidance - much of it dealing with the gnarly edge case stuff or unfortunate past choices). Who is going to step up to the plate to write these kind of books for C++ now that Scott has retired from it. Will need to be a person with rather high expertise in the language. And more books will be necessary - just look at these cpp on 2018 videos and how they're all ripe with the kind of matters that Scott's book series has always addressed. Gee, Concepts alone requires a book all to itself to better explain how to master these new features (not just consume concepts but understand how to implement them well for oneself). I tried to breeze through the Concepts Web pages and just came away struck at how deep this feature area is, much re-inforced by cppcon sessions on Concepts. I'm weighing investing more time on C++ vs just switch to Rust and start investing in learning that well.
@@TheSulross Go can disable GC. My point is that Go can replace C++ for many uses, but not necessarily all uses. (EDIT: Actually my point is that none of these languages will displace C++ due to network effect, but they might be better for certain projects anyhow.)
4 ปีที่แล้ว
The auto[]= behavior, non-intuitive but logical. Copy the main object and then make references to its members. One would think a temporary is created, then a copy/move for each member. But that's less efficient.
it's probably a local installation of the compiler explorer on his machine. it's understandable that the one on the net won't let you run arbitrary code, but a local installation does not have such qualms.
two allocations are needed simply for the two elements of the std::initializer_list object which is passed to the constructor, and then 3 allocations for the std::vector and its two elements (which are copy-constructed from the elements of the std::initializer_list)
Surprises! I understood Moved-from objects still have to be destroyed! Even without a named object we have to be thinking about lifetime! Complex rules allow for the lifetime extension of temporaries that are assigned to references! Lifetime extension rules apply recursively to member initializers! std::string is highly optimized, don't underestimate it! std::initializer_list invocations create hidden const arrays! std::array has 0 constructors, for efficiency! to be continued
4 years later not much has changed. Jason's talk about Surprises in Object Lifetimes, Herb Sutter's talks on overhauling the language syntax entirely with syntax 2, Nicolai Josuttis's talk about The Nightmare of Initialization, personal experience, and the icing on the cake - the NSA's 2022 official recommendation to strategically migrate away from using C++ entirely - For new projects, I would not pick C++. Rust, Python, C# - I'll even suffer Go or TypeScript over this. For those already in the trenches maintaining existing code you didn't write - I'm so sorry.
I love Jason's style. His talks are always super entertaining.
Jason it's always a pleasure listening to your talks and watching your youtube videos. Thanks for your contributions.
This talk was fantastic!
20:56 Jason, if your audience can’t even ask questions about what you just said it is not the audience fault, it is the instructor’s.
For me a successful lesson is when I have been so clear that everyone understood.
I like watching these videos and keep coming Empty handed in terms of what I have learned at the end. It is possibly related to the flaky/fluidic/all-over-the-place opinion polls which he keeps taking.
26:30 On both gcc and clang only aggregate initialization extends lifetime.
Additionally gcc is smart enough to notice this and warns about unused variable only if it does not extend lifetime of object with destructor with side effects.
Yes, I think Jason got this wrong. The reason is that if you use a constructor, then the member initialization is from a constructor argument not from a temporary, and hence it won't extend the lifetime of the temporary you pass to the constructor.
I think that vacuous is a term used to describe a data that is destructible or supportive to confined randomization, which are options of the programmer.
"If you know who I am and have seen my previous talks, you may want to move to the front"
I would have done that and yelled wrong or right answers because Jason reaction will be fun
43:45 "that is not the opening curly for main"
That's because that was put at the end of the previous line so it's easily overlooked.
And that's why I've always been in the "put the curly on the next line"-camp. Apart from visual separation of multi-line parameter lists and the function body.
57:26 Small typo "Dandling" should be "Dangling"
I just tried the std::string_view returning function with a const char[] local array.
GCC (pre-12 trunk) now warns against this (with a cryptic error message) __only in O3 mode__. (it prints garbage/nothing when using any other optimization level).
CLang (pre-14 trunk) compiles fine and does print "hello world" __only from O1 and up__, it still prints garbage for O0 (but never warns).
I find it strange that compilers are still not able to detect "local variable use outside function" UB.
Const ref lifetime extensions make me uncomfortable. I would rather just get a compiler error if I try to take a reference of an rvalue, imho. The fact that "const T &x = getRValueT();" is valid and compiles without error makes me so uneasy. This feature seems more like a hack to protect silly mistakes where a compiler error (or even just a warning) should have been enforced instead. The destruction of a reference should never trigger a destructor :\
Blake Scherschel That exists for backwards compatability with temporary Lifetime Extensions from before the days of &&. It basically allowed you to construct a T from and rvalue pre C++11.
It's useful in generic code. It lets you use auto const &x = (expr); or auto &&x = (expr); to bind the expression to an identifier without having to know whether expr is a glvalue or a prvalue.
It allows you to pass a temporary to a function that accepts a const reference. And we all do that all the time, so this feature is not obscure by any means.
void foo(const Bar& bar) { ... }
foo(Bar());
48:36 If I were to do something with s and get_Holder().s seperately before returning it can't move right? Because you're technically using both objects? I'm I correct in my understanding that it will only do this if it knows it CAN be moved at all (ie. you're not using the moved-from object anymore before returning)?
Inside get_Data, you can't do anything with s until it's initialised. It's initialised from get_Holder().s, which is the only usage of that. You can use s as much as you like after that, until it's returned -- afterwards of course you can't do anything with it since you've returned. None of this changes the pattern of calls. You can't use "get_Holder().s" *again* without either calling it again (which is a separate usage that will make the same calls again) or just using s, since that's a local (moved) copy of the same object anyway.
When C++11 hit the scene that rekindled my interest in C++ and I went and wrote a significant amount of C++11 for a special project. But even as new and cooler things are being added to C++11 to get us to C++20, videos such as this one are demoralizing my interest in staying with C++ going forward. I've now watched several Cppcon 2018 videos and nearly everyone of them was something on the perils of C++ if you don't understand it to an arcane level. (Two exceptions was on C++ for Nividia GPUs and a cool one on template engine to parse regular expressions at compile time - and even evaluate them.)
A new book appeared this year The Rust Programming Language. I've been going through it and am seeing that it's possible for a rank and file programmer to actually master the breadth of the Rust language. With C++20, Concepts will, yeah, make it easier on rank and file programmers to consume template classes and compose somewhat simple template classes themselves, but to really master C++ generic programming just ballooned another order of magnitude in breadth complexity (and it was already exceedingly arcane).
All the special case gotchas and surprising behaviors of the C++ language just further demoralize. There are so many special knowledge issues to track and keep up with. A programming language really shouldn't have this much cognitive baggage overhead.
It really does prove the case that their needed to be a fresh start on a new systems programming capable language and thus far Rust is the best candidate for that.
To some extent, it is also that C++ developers love to focus on these cases, and to some extent also love to play in the language approaching the corner cases. I recently encountered a devastating performance bug in a Java application. One of the dependencies were using WeakReference when they really probably meant SoftReference. That, in turn, caused total performance havok under specific loads with a subset of JVM versions.
In fact, coming from a C++ mindset might have made it easier for me to spot this. The team had already isolated the method were this was done as the bottleneck, but they didn't have the "object liftetime" mental alarm firing off.
There's Rust, but also D, Kotlin, Go, and maybe more. They're all really good, but C++ has the network effect going for it.
@@-taz- to be a true systems programming language and that could be used in embedded programming, it needs to be a language that does not have a complex runtime requirement - that rules out all the garbage collection memory management languages. golang is a good language and is very simple language, by relative comparison to many others, and it's good for a certain species of quasi systems programming - the Docker daemon being most famous example. Golang sweet spot is services and tools - especially quickly developed custom tools. But golang uses garbage collection memory management and has a substantial runtime - it doesn't qualify as a systems programming language in the vein of C, C++, D, or Rust.
@@carlnettelblad1139 I work on my C++11 code base project on an intermittent basis (a few weeks go by and then I go dive back in to add new feature, etc). I often grab my Scott Meyer book and go re-read sections of it to get my head back into best practices guidance - much of it dealing with the gnarly edge case stuff or unfortunate past choices).
Who is going to step up to the plate to write these kind of books for C++ now that Scott has retired from it. Will need to be a person with rather high expertise in the language. And more books will be necessary - just look at these cpp on 2018 videos and how they're all ripe with the kind of matters that Scott's book series has always addressed. Gee, Concepts alone requires a book all to itself to better explain how to master these new features (not just consume concepts but understand how to implement them well for oneself). I tried to breeze through the Concepts Web pages and just came away struck at how deep this feature area is, much re-inforced by cppcon sessions on Concepts. I'm weighing investing more time on C++ vs just switch to Rust and start investing in learning that well.
@@TheSulross Go can disable GC. My point is that Go can replace C++ for many uses, but not necessarily all uses. (EDIT: Actually my point is that none of these languages will displace C++ due to network effect, but they might be better for certain projects anyhow.)
The auto[]= behavior, non-intuitive but logical. Copy the main object and then make references to its members. One would think a temporary is created, then a copy/move for each member. But that's less efficient.
thank you, amazing presentation!
Illuminating talk!
How did you get the a.out option in compiler explorer ?
it's probably a local installation of the compiler explorer on his machine. it's understandable that the one on the net won't let you run arbitrary code, but a local installation does not have such qualms.
So many surprises...
I am a fool and don't get why the generated initializer code has a + 2 in it.
two allocations are needed simply for the two elements of the std::initializer_list object which is passed to the constructor, and then 3 allocations for the std::vector and its two elements (which are copy-constructed from the elements of the std::initializer_list)
I believe its equivalent of begin and end, where end is "past the last elem"
Surprises! I understood
Moved-from objects still have to be destroyed!
Even without a named object we have to be thinking about lifetime!
Complex rules allow for the lifetime extension of temporaries that are assigned to references!
Lifetime extension rules apply recursively to member initializers!
std::string is highly optimized, don't underestimate it!
std::initializer_list invocations create hidden const arrays!
std::array has 0 constructors, for efficiency!
to be continued
That gcc warning... weird.
4 years later not much has changed. Jason's talk about Surprises in Object Lifetimes, Herb Sutter's talks on overhauling the language syntax entirely with syntax 2, Nicolai Josuttis's talk about The Nightmare of Initialization, personal experience, and the icing on the cake - the NSA's 2022 official recommendation to strategically migrate away from using C++ entirely - For new projects, I would not pick C++. Rust, Python, C# - I'll even suffer Go or TypeScript over this. For those already in the trenches maintaining existing code you didn't write - I'm so sorry.
first