📝 *Get your FREE Rust cheat sheet* : www.letsgetrusty.com/cheatsheet
@Nuclear8682 жыл бұрын
3:15 a little correction: In the case of std::ofstream, when it's destructor is called, the file will be closed (it is closed by the filebuf, which represents the internal stream buffer). In other words, std::ofstream manages the acquired file.
@letsgetrusty2 жыл бұрын
Thanks for the correction!
@ronensuperexplainer2 жыл бұрын
Yeah, I started questioning my C++ knowledge at that point in the video
@ruszkait2 жыл бұрын
The stream API in the standard C++ library is the first RAII resource manager - for files. Later came more RAII for memory management - the smart pointers. The real example would be here if the fopen/fclose API. FILE* fp = std::fopen("/tmp/test.txt", "w+"); std::fwrite("hello", 5, 1, fp); std::fclose(fp); Here we leak the file handle if there is an exception or we return between the fopen and fclose.
@abhinavk0929 Жыл бұрын
@@ruszkait yea, he probably meant to use the C version but ended up with RAII class
@Possseidon2 жыл бұрын
10:09 destructors are actually called in the reverse order that the objects have been constructed. This is also true for members of a class and even globals. It just makes sense, as you could imagine passing a reference to a previous object to a new object. If this new object's destruction needs to do some stuff on the previous object, we can be sure, that it lives long enough.
@letsgetrusty2 жыл бұрын
Yeah thanks for pointing that out
@danielsantiago11282 жыл бұрын
In a hierarchy chain, the order in which destructors are called in C++ depends on whether they were declared virtual or not.
@brainplot2 жыл бұрын
Nice video but the C++ example showing how a file handle would not be closed if an exception is thrown is incorrect. ofstream is a RAII wrapper around a “raw file handle”, meaning the file handle would actually get closed as the ofstream instance falls out of scope (including if the exception is thrown).
@letsgetrusty2 жыл бұрын
Thanks for the correction!
@user-if7lb8zy8i2 жыл бұрын
looking clean bogdan :)
@harikrishnanb72732 жыл бұрын
i got some doubts!! the "variable" car is a object or instance of "class" CarManager and is not a pointer to "class" Car. so you can't directly access anything from "class" Car. you can indirectly do it by "car.p", since it is a pointer to "class" Car, wait a second but "p" is a private member so you can't acess it. hence technically no way to aceess "class" Car, it's method, and it's members. In case of make_unique and make_shared, they give you a pointer to "class" to Car , so you can access it's members by car->member or (*car).member . so i think the CarManager implementation is not appropriate. C++ guys, correct me, if i am mistaken.
@harikrishnanb72732 жыл бұрын
For clarification: let's assume "class" Car as a member year( denoting the year of manufacture) of type int. "auto car=make_unipue();" now i can access the year by "car->year" . but if "CarManager car = CarManager(new Car);" how can you access the year or anything at all ??
@rastaarmando70582 жыл бұрын
@@harikrishnanb7273 u have to overload the -> and * operators just like like how unique_ptr and shared_ptr to access the car member: Car& CarManager::operator*() { return *p; } Car& CarManager:: operator->() { return p; }
@harikrishnanb72732 жыл бұрын
@@rastaarmando7058 i am a beginner in C++ , THANKS for your info. so, the implementation provided in the video is incomplete or not correct, right?
@rastaarmando70582 жыл бұрын
@@harikrishnanb7273 yes, this dude dude is not a c++ guy; he said he comes from a JavaScript background.
@harikrishnanb72732 жыл бұрын
@@rastaarmando7058 👍
@philstubblefield2 жыл бұрын
Thanks for the excellent introduction to RAII! As an experienced programmer who has never worked with C++, I had a basic understanding of what RAII means to that community, but your examples were very helpful! I'm looking forward to your discussion of OBRM in Rust!
@philipreinhold11802 жыл бұрын
This is by far the most clear explanation of RAII I've seen so far. Thank you!
@HylianEvil2 жыл бұрын
I can tell the channel is taking off because my boy is looking more and more dapper
@Speykious2 жыл бұрын
I come from C so anything related to C++ has always been very confusing to me. This video really helps me getting its concepts. :D
@shushens2 жыл бұрын
What did you try to understand RAII before that didn't work for you?
@Speykious2 жыл бұрын
@@shushens RAII in particular? Nothing really. I approached Rust from my knowledge in C and very rarely have to deal with anything C++. When I have to read C++ code though, especially when there's a native memory leak involved, it's a real pain to deal with, but I never really took the time to properly learn the language.
@HermanWillems2 жыл бұрын
@@Speykious Well i see Rust as a language which can be either C(on steroids) or as good as C++. The thing is C++ isn't particularly worse than Rust. But C++ can't be C. But Rust can. Also RAII in C++ is a must, and also MOVE Semantics in C++. Which i hate in C++ it's just one big mess. In Rust this is handled beautifully. I see Rust not better as C++. But just like C++ with more utility and lessons learned from all things that are learned during the start of C++ and now C++20. They can make C++ alot better, but they would destroy backward compatibility. What i like about Rust is... that it can be C. (C++ cannot) and therefore program for example much easier low level devices like microcontrollers and such. Rust is gaining a lot of traction in the Embedded world. For example STM32 microcontrollers and such. On such devices if you can eliminate a lot of human prone mistakes done in C, it can save a lot money. Because C in microcontrollers are not updated easily, and must be GOOD before the product is shipped. Rust helps a lot with that, especially the compiler.
@vorrnth87342 жыл бұрын
@@HermanWillems Of course C++ can be like C (that is one of its problems). That is how it started. And C is almost a subset of C++. There are differences but most of the C language could also be compiled by a C++ compiler.
@danielsantiago11282 жыл бұрын
Well in my case it's the other way around, I have enough experience in C++ and in my current job I have to use C, the truth is that sometimes I have a really hard time :P
@pdd93662 жыл бұрын
A Rust channel with a nice C++ video. Keep up the good work.
@johaneriksson4332 жыл бұрын
Wow this was great, you need to make more comparison videos with c++ and possibly other popular languages with rust!
@apivovarov2 Жыл бұрын
@3:08 You do not need to explicitly close fstream in C++. The fstream object will be closed automatically when it goes out of scope.
@kcvinu2 жыл бұрын
I've learned C++ from this video. You are an amazing C++ teacher. Thanks a lot.
@marawanlotfy14772 жыл бұрын
one key to note that php uses this technique of reference counters for variables and the garbage collector will frequently check to free memory that counts by zero
@nextlifeonearth2 жыл бұрын
At 10:10 you say car is cleaned up and then car2. That's the other way around. Whatever is created first is destroyed last. This makes much more sense, because you can add an object ref to another object and if you were to destroy it first, it would orphan that reference, causing a segv. It's first in, last out.
@alagaika85152 жыл бұрын
I think the CarManager is not a good example of RAII - it cleans up memory that it does not itself allocate, but that gets passed in. There is nothing preventing be from passing the same pointer to two CarManagers, which will lead to a double free.
@jimhewes75072 жыл бұрын
By the way, I believe the name Recourse Acquisition Is Initialization comes from the object being fully initialized in the constructor code so that any object that is acquired through construction is already initialized and can be used. The alternative is that initialization code is not put in the constructor but in a separate Initialize() function. The user/caller is expected to construct the object and then immediately call Initialize() to initialize it, and the object is considered not valid and should not be used until Initialize() is called. The motivation for doing the two step process is that constructors cannot have a return value and so cannot report if the initialization code failed in some way. To put the initialization code in the constructor would require exception handling which some people prefer not to use. However initializing in a separate function leaves the possibility that a user could accidentally try to use an uninitialized object. So the technique of RAII ensures that all successfully acquired objects are also initialized.
@babatona2 жыл бұрын
Nice, your content quality is better and better!
@danielmilyutin99142 жыл бұрын
Hi, `ofstream` file is quite redundant example since `ofstream` itself is RAII-type handle. You could use native C `FILE` with `fopen`.
@putzz677672 жыл бұрын
Clean explanations. Even for non english speakers. Greetings from Brazil!!
@9SMTM62 жыл бұрын
Without having watched it so far: It's the same thing, isn't it? Except that OBRM has a much better name, better defaults and clearer semantics (move by default, move is destructive) and is more prevalent because there isn't the temptation of just using straight C code.
@letsgetrusty2 жыл бұрын
Yes that's a great summary
@Luxalpa2 жыл бұрын
It's not exactly the same thing but it's very close indeed. The issue with the smart pointers here is that in order to share you will need a reference counted pointer (as the C++ compiler does not do borrow checking), whereas Rusts version works fine with the normal pointer (in most cases), meaning it has less overhead. For example, if you had a bunch of unique pointers stored in a struct, Rust allows you to borrow them in order to do operations on them, whereas there'd be no equivalent in C++
@9SMTM62 жыл бұрын
@@Luxalpa you mean references. Rust has Pointers and references, pointers are explicitly the way to opt out of the borrowchecker (with unsafe). And C++ also has references. And you can arguably do more with them, it's just not necessarily always safe (and it's also not explicit at call-site, which I find fairly annoying). So I'm not sure what you mean, what you said doesn't make sense to me. Rust does have one aspect where it is "faster", and that is because of the borrowchecker with its mutability rules it can optimize more aggressively in a few situations. But that doesn't seem to relate to what you're saying.
@berylliosis52502 жыл бұрын
@@Luxalpa C++ allows you to borrow even more freely than Rust, it just doesn't know about it - it forces you to keep track of borrowing rules (less strict than Rust's) yourself. What Rust *does* allow you to do is be more confident in your borrows - when you borrow, you _know_ , without even checking, that it'll last as long as you need it to. That lets you easily use references in contexts that would be very dangerous in C++ (and therefore would likely end up being replaced with copying/RC code)
@Luxalpa2 жыл бұрын
@@9SMTM6 The words "pointer" and "reference" are terms that have different meanings in different languages. I used them here interchangeably as I was talking about a broader language concept and not to their specific implementation. To me, both of these words mean the same thing, a reference (or pointer) to a memory address but I understand that it might be confusing. I didn't even know that you could opt out of the borrow checker in rust. Regardless, there's no such thing as "you can do more with them" as both of these programming languages are touring complete, meaning you can do everything. The point here is in fact the opposite - which one is more restricted (= specific). I never made the claim that C++ does not have pointers (or references which are equivalent). You already kind of said it yourself, the C++ pointers / references don't have any sort of lifetime checking on them. For that, you need smart pointers or shared pointers, which - as I said in my post - have a runtime overhead compared to the Rust version which does not need runtime tracking (reference-counting) to implement sharing for the most common scenarios. The borrow checker optimizations are - to my understanding - not completely live yet and have to be enabled with an experimental flag, but I am not referring to those. Just to clarify: This topic is not about references / pointers; it's about memory management. If you're using raw pointers (& or * in C++), then you're opting out of memory management entirely. RAII allows you to have some memory management at compile time, but it breaks down for objects that can change ownership or be used by others (for example to read); it still works somewhat using shared pointers, but you'll have to deal with reference-counting at runtime. Rusts memory management can handle many of these situations before having to resort to runtime checks.
@Khalooodi-he3we12 жыл бұрын
You’re amazing in explanation bro, thanks
@brianrieman58982 жыл бұрын
I'm by no means a solid C++ knowledgeable person - but in your raii.cpp memory_example_2() where does 'CarManager car' get allocated in memory? ..on the stack (like video states at/around: 4:48)?... - or on the heap (like the video states at/around: 6:55)?
@_jdfx2 жыл бұрын
thanks Bogdan! bonus C++ knowledge as well, great!!!
@CTPATEX2 жыл бұрын
4:03 Our CarManager class has a bug that causes the "double free" problem.
@nextlifeonearth2 жыл бұрын
Shouldn't be in the way he's using it. Passing in the pointer is risky though, you can delete it outside of the class. It's better to pass the constructor parameters and create the heap instance in the constructor.
@harshpatel530111 ай бұрын
Where ar reference counts store ? is it in heap memory ??
@doezage2 жыл бұрын
Part 2 better come tomorrow
@danielrhouck2 жыл бұрын
Your example at 3:05 isnʼt good; the `file` class *already* closes on destructor. EDIT: Oops, should have checked other comments first.
@kjell-olovhogdahl65572 жыл бұрын
C++ has become bloated over the years and if Rust can come up from behind and pick up the "good stuff" and leaving the mess on the floor this will be a good thing! That said, I think the actual "problem" with C++ is how easy it is to fall into the cracks rather than not being able to express ownership at compile time?
@alexandernyberg86682 жыл бұрын
Off topic but the C++ file example is actually safe because ofstream implements RAII, C and old C++ FILE * would be a better example
@inx18192 жыл бұрын
Hi, quick question (hopefully you respond) I'd really love to see a video on async rust. It's one of the Rust topics I cannot wrap my head around, and a nice explanation from you would be incredible. You're the person who finally broke the ice for me and I can't be more thankful for making Rust just click in my head.
@letsgetrusty2 жыл бұрын
Yup, that’s on the list!
@farzadmf2 жыл бұрын
EXCELLENT explanation, great job!
@AbhinavKulshreshtha2 жыл бұрын
What would be the RAII equivalent for C language which doesn't have classes?
@JMANN2402 жыл бұрын
There is none, it all must be done by the programmer using “malloc” and “free”.
@AbhinavKulshreshtha2 жыл бұрын
@@JMANN240 RAII is a programming pattern. There must be a programming pattern used by C programmers for avoiding memory leakage bugs?
@mojacodes2 жыл бұрын
@@AbhinavKulshreshtha RAII is facilitated by constructors and destructors, neither of which is in C.
@AbhinavKulshreshtha2 жыл бұрын
@@mojacodes I know, that is why I am asking about an alternative pattern that can be used in C programs?
@Luxalpa2 жыл бұрын
You can't do it in C as it's not a pattern, it's a code-generation feature from the compiler. As there is no way in C to automagically run functions without you explicitly asking for it, that means there's also no way of automatically removing resources (other than those on the stack). This is a feature of C as it allows you to easily track and understand what your program is doing without "overlooking" invisible function calls from overloaded operators or destructors. The benefit is that it's easy to understand what your program is doing but the cost is that it's your responsibility to handle resources, function calls, etc manually. The closest you'd get for C is by using macros or going for a pattern in which the bits between resource aquisition and destruction are moved out to a separate function.
@PHANTOMWORLD Жыл бұрын
love you buddy thank you so much for the valuable knowledge
@happymt57352 жыл бұрын
谢谢,简单明了。期待part two
@Mal-nf2sp2 жыл бұрын
Thank you for this.
@yassin_eldeeb2 жыл бұрын
Looking nice bogdan.
@rastaarmando70582 жыл бұрын
3:15 that is false.
@Megalcristo22 жыл бұрын
Yep, since C++11 when the file object get outs of scope the file close automatically.
@winnie86142 жыл бұрын
Isn't it also RAII?
@bigsbypt2 жыл бұрын
Very instructive.
@DipsAndPushups2 жыл бұрын
I expected OBRM to mean object relational mapping haha, the video is about something completely different
@vorrnth87342 жыл бұрын
Just for Info: std::move is not a function. But it is another example of a confusing name since it does not move anything (by itself). It is an RValue cast and car is moved to car2 since the move constructor takes an RValue while the copy constructor would take an LValue.
@homelikebrick422 жыл бұрын
std::move is a function
@Criteria12 Жыл бұрын
Have you ever heard about SMART POINTERS in C++
@mosth8ed2 жыл бұрын
Great video, as usual, but please, no more slides with solid white backgrounds. My eyes, man. Think of my eyes.
@Luxalpa2 жыл бұрын
My eyes actually hurt from the dark backgrounds...
@GlobalYoung72 жыл бұрын
Thank you
@tawandagamedevs2 жыл бұрын
Also we barely use exceptions in c++, they lead to many errors. Exceptions sucks. I mean i dont use them
@ashtangacenterodessa2 жыл бұрын
Cool video!
@herrxerex84842 жыл бұрын
LEAVE C++ EMBRACE RUST !!!
@danielsantiago11282 жыл бұрын
Ever since I discovered rust I've been wondering what the difference is in terms of ownership compared with C++ smart pointers. I have been programming and teaching C++ for many years and I think there is nothing this language cant do. This is actually both good and bad, as inexperienced programmers are more likely to make mistakes. Good programming practices, one of them exposed in this video, should be mandatory in C++ training.
@thegeniusfool Жыл бұрын
Awkward example since the fstream classes indeed do call close in their destructors, i.e., already does do RAII. But ok.
@dorktales2542 жыл бұрын
He shaved?!!!??
@Elduque402 жыл бұрын
New look 😁
@samhanna73822 жыл бұрын
dude looks like he about to meet his girlfriends parent's
@GolangDojo2 жыл бұрын
Lol bruh why you looking like an accoutant intern
@exoticcoder53652 жыл бұрын
Wow you look super handsome dude !
@BohdanTrotsenko2 жыл бұрын
I like your videos because they are consice, but this one has quite a space for impromenent. (leaving apart the already mentioned ofstream destructor) Even not the video itself, but the naming. Please name it "C++ RAII vs Rust OBRM - Part 1 - RAII in C++; unique_ptr, shared_ptr" I would click through and not watch it. (and watch some other video of yours instead)
@doezage2 жыл бұрын
Looking like a school boy
@proudmoroccan81642 жыл бұрын
C++ has many design flaws, and no wonder Linus Torvalds the father of Linux OS dislikes it.
@AbhinavKulshreshtha2 жыл бұрын
What would be the RAII equivalent for memory safe C programs? Linux kernel has relatively very low memory leaks considering project of that size.
@vorrnth87342 жыл бұрын
@@AbhinavKulshreshtha In C you better follow the single entry/single exit convention. If you do do you can place your clean up code at the exit.
@Luxalpa2 жыл бұрын
The reason Linus Torvalds dislikes C++ has little to do with its design flaws. It's primarily because it's intransparent and magical - which is fine for high-level applications, but if you're writing a highly optimized and secure piece of software like the Linux kernel, he prefers to know exactly what's going on and C gives that advantage. No invisible or unintuitive calls. Yes, the developer has way more responsibility instead, but at least all of the states of the program can be easily figured out by just reading the part in the code. No hidden changes, etc.