@@Robertoclos-ib7ccIn the name of the Spaghettimonster, i invite you to worship the Spaghettimonster alone: I bear witness that there is no god but the Spaghettimonster, and I bear that your Dad is the messenger of the Spaghettimonster. These words make you a servant of North Korea.
In Rust you fight the borrow checker, in c++ you fight the entire compiler, the standard library, the build system in fashion this season, the human laziness, and at least 80% of the c++ commitee all at once.
@@KX36 you think you've won, but the real guerilla war is only starting. With UB behind every corner, and memory corruptions scattered in the most unexpected places...
So I've been using C++ for many years now (tho I'm not a dev by trade) and all of these papercuts that he's listed, aside from the `const` papercut, were things that you have to be *taught* wrong in order to do it wrong. How is it not obvious that `=` is *always* a copy? You read one page of a C++ for dummies book and it will tell you that with `=` you copy a value from one place to another. It doesn't say "move". Also what kind of abomination is `void funct(const char void* mesg, [...])` who dropped this man?
A lot of people will come from a reference counted language like Java or JS and in those because you're actually only passing around pointers/reference when assigning things, it seems like = is a reference not a copy.
@@anlumo1 True, but where do you put the line what someone has to know and what not? I think there are at most 5 people on this planet that know every thing about C++, but there are some very very basic things every one who writes C++ code (and is not an absolute beginner) should know about. And assignment is one of those things. And 'because language X makes it the other way around' is not an argument but a distraction. Because FORTH uses UPN the way C++ makes calculation is bad and should be changes! :)
I really doubt that someone who is talking about smart pointers doesn't know `=` always copies. Also wasn't that entire part of the article basically about how implicit copying is default?
I'm a c++ dev and really I disagree with this man. For me, the biggest problems are : - Optionals and variants are not first class citizens (meaning, you cannot at compile time unsure that the content of the object has been check before unpacking it (see Rust and Zig for this type of things)) - inheritance is just pure pain, I am good with the language, I can understand most template wizardry etc but the moment you throw multiple inheritance in the mix, it is hard to get what is going on and I have to travel between multiple files to get it (just a stupid way to make your code obscure). - exceptions are a mess, like the const keyword, c++ has a noexcept keyword, which a few devs might use, but then nobody does use them, making it a pain to know if you have to catch something and most often, you just never try catch anything and hope that your test may tell you to use one.
That last one is a pain point of mine. It’s also risky to declare something as noexcept in a large project because someone will violate that contract. On balance I think violating noexcept is worse than not adding it in the first place. Needs more work!
@@khatdubell to be honest, I just try and return value errors like in C. It's not very readable but at least the error is contained and not propagated to god knows how many calling functions.
@@DN-fr2ez Well there are people not knowing this. Plus sometimes it's just not "multiple" inheritance but "inheritance everywhere" which in my opinion os just as bad. I trier going into some codebases just to need to jump to many places all the time. At some point I just dread inheritance if it means getting code from parent class. One abstract class from time to time, why not.
Tuples are actually good as return types in C# since you can name the parameters instead of having to use .0 or .1. I almost never use "out" parameters.
A function should return one thing. Make a class for the return value if you need to. Narrower types are better and it communicates intent better. At least you're not returning a string tough. Good job.
@@FalcoGer I agree with you, but sometimes it feels overkill to create a class just cause you want to get back 2 things instead of 1, especially if it's for some private functions in a class which are called by other public functions in the same class - or to put in simpler terms, when it's a one-off scenario and the function would not really be called anywhere else or need that data passed around together. The most common case where I'd return a tuple if it were a public function is say a function which queries the database or calls some external API, I could return an enum and an object. The enum indicates either success or a specific error in cases where there are well-defined outcomes (e.g. here's the data, or data didn't exist, or exists but you don't have permission etc, to save multiple function calls/trips to the database to first check those things), while the object is some nullable class (lets say a Customer object) which would be null if there was an error. Yes, to make it return 1 thing then something like a DatabaseResponse could also work which has the result and object. But again, such a function probably only gets called by 1 or few endpoints and don't have a need to pass them around together, so I just use a tuple, so I get back basically two "destructured" variables which I can give a friendly name like "queryResult" and "customer", rather than using "response.data" to get at the data. I understand this is just a style preference.
I don't know if I just had an insanely insightful professor when learning c++, or if I have just used it enough to get over the learning curve, but it seems that most issues with c++ come from people trying to write C code in C++. Yeah, it's valid syntax and will work, but that's not the point. If you "embrace the c++" and use the features as intended and not try to overthink it, I think you'll have a better time with it. Remember that performance and generics aren't the be-all-end-all and that sometimes using other paradigms, like functional programming, lambdas, etc., can be a very nice supplement to your C++ coding experience.
"I don't quite understand that" unique_ptr is move only. A default constructed unique_ptr is going to be a nullptr. But per the rules of this new class he's talking about, you don't allow nullptr. So you can't copy it into place. Now, because you disallow nullptr, you can't move it into place. The only option left is to pass it by reference.
@@insu_na To pass the pointer, when you do a move in a unique_ptr the variable is left with a nullptr to guarantee that it is unique instead of having the pointer duplicated and later you can reuse the variable to assign it to other pointer.
@@insu_na Sometimes when you have a unique_ptr as a member in a class and are interacting with some C api you need to first set up some stuff in the constructor with that C api so you can't set the unique_ptr in the initializer list. In those cases you might want to make them nullptr temporarily.
@@insu_na "Why would you create an empty unique_ptr? that doesn't even make sense..." Well, there are, in fact, plenty of reasons, though i wouldn't label any of them as "good". People don't create empty smart pointers because they _want_ to, they do it because they _have_ to. Something i've had to do on many occasions. Secondly, welcome to the ethos of C++. Its not the job or the goal of the language to decided the why's of what you may or may want to do. It provides the toolset, you provide the use of the tools as you require. "You should always use make_unique() anyway" You can use make_unique to make a defaultly constructed (null) pointer.
Unique pointers in C++ get completely compiled away and are only compiler safety mechanisms. Only shared_pointers have overhead and that is the minimum overhead required for reference counting (so like using an rc in rust)
There's a talk titled 'There are no zero cost abstractions' which has a section on why unique_ptr can have a significant overhead in very special, high-performance situations and across boundaries? I recommend watching that part, very insightful.
unique_ptr in C++ must use the allocator (heap by default), some cases of compiler optimization can happen where the heap allocation is removed, but this is not the general case, they aren't compiled away.
What's your point xD It only proves that this language sucks really early. The funniest Clowns are the C++ devs who think the language gets better with every version, but in reality the language gets more and more unusable because of all the bad design decisions. Just take Modules f.ex, until this date the most used C++ Version is 11,14 or 17. It will take multiple years until some C++ libraries will support modules and until company's actually allow the newer versions in their codebase. There is literally NO point in rewriting C++ code over and over again if we have way better alternatives like Rust, where safety and the really good type system come by design. Every C++ Game Dev I have come across, is entirely annoyed by C++. No wonder why nearly every game is a buggy mess if the codebase is C++. I'm really happy that C++ is slowly replaced everywhere possible. Google rewrites C++ Android Parts, MS rewrites Windows Parts etc. It will take some time, but the time is ticking for C++ and that is very good
@ITSecNEO you see, the problem is you don't look at facts but instead bring fanatism to the conversation. As of 2024, here is a small list of major desktop and mobile apps that still uses c++: google chrome, Unreal engine, Blender, Microsoft Visual Studio, Maya, Photoshop, Firefox, Autocad, WinRar, MySql, Spotify, Dropbox, VmWare, Tesla Autopilot software, Microsoft Edge, Opera, Safari, Unity, Adobe premiere pro, Amazon aws, docker, Whatsapp, Snapchat, Tiktok, and of course both major oses Windows, Linux, Mac,... Oh man i could go on and on. Wether you like it or not, c/c++ is everywhere, even on the device you are using to write comments on youtube, and the very core engine that feeds you this youtube video. So i don't know where you find your claims but it's not from real life.
1. I think the problem with std::tuple can be solved with structured bindings. 2. IIRC Herb Sutter is working on a new modern C++ syntax which transpiles entirely to regular C++. His transpiler is named cppfront, inspired by the cfront compiler which was the 1st C++ compiler which compiled C++ to C code.
1. Is addressed in the updated article in the description of the video. Essentially, Hartzell's take is that it's a half-way fix because it isn't first class tuple support.
@@curlyfryactual it _is_ first-class, though. it's in the standard library. there's no need to add features directly to the language if the language is already expressive enough to express them effectively in library code. should filesystem access be in the language?
I remember learning about the copies back in 2008 - 2010 while I was learning c++. The book Accelerated C++ was really good at pointing this stuff out. They sure as heck didn't even mention this stuff in my college c++ class I took later!
Well this was dumb. What the hell is slow about a unique_ptr? And why are you using shared_ptr, it's a very rare case when multiple things own something. C++ can be misused, yes, that's what reviews and seniors are for. Most of the things brought up, like out parameters can be solved by a sensible company coding policy.
Smart pointers and RAII in your own classes get you all the memory safety. You never have to new and delete. std::visit and std::variant kind of do what Rust enums do, C unions can also be used but not as safe. C++ has tuples, but structs are always better. Smart pointers used correctly are actually no slower than raw pointers; people do use shared_ptr wrong though.
One of the biggest wants for me is to have match/switch on enum/variant that compile time checks for coverage, something I am not aware of existing in C++ at present.
Reference invalidation is quite possible without borrow checker, std::variant is terrible compared to Rust Enums, as you agree by saying they “kind of do” what the Rust one does… Rust has the real deal!
Agree with most, except "structs are always better." Use struct if you need struct. The power of std::tuple is that it's a generic type and can be used in generic code. In fact, some algorithms work on tuple-like types (tuple, pair, array). The key to genericity is concepts, which allows multiple types to be used in uniform ways.
It's such a horrible language that *most* (like 99%) of the software were written in this language long before that abracadabra rant in the video: game engines, games, operating systems, video and graphics software. I really don't get it. C and C++ give you freedom, you can do whatever you like. Introduction of additional abstraction into programming languages makes it extremely difficult to maintain all possible design questions. In my opinion C/C++ to this day are still the best programming languages and those who pass on studying them miss a lot in terms of programming skills.
Just because it can be and is written in C, doesn't mean C is the best choice. By this logic, if everything was writen in asembly that would be the best programming language, and I doubt I will find many ppl defending that position.
@@someonespotatohmm9513 Well, it's just my take. I really don't see how Rust or Go are more advanced to C/C++. They are hyped as the "next big thing", but in essence it's pretty much the same stuff with slightly different syntax. That's my point. Switching from Assembler to C and the C++ was really a game changing thing, you could feel boost in productivity. But switching from C/C++ to Go/Rust doesn't feel like that at all.
@@alexandersuvorov2002 Writing stuff in Rust only makes my head hurt because the syntax is so convoluted. If I was young enough to still be able to learn things maybe I might appreciate it, because it does some genuinely cool things, but I'm no longer capable of learning new things, so I'll stay with C++, because it's good, too.
@@insu_na I'm open to new ideas and new programming languages and I definitively don't want to be dinosaur advocating for FORTRAN and COBOL. I really feel sad when I hear people complaining about the new tech while I can clearly see what future is going to look like. For example, to me JavaScript was "wow moment", while Java Applets and Adobe Flash not so much. JavaScript clearly has bugs, but the entire concept of reusing SmallTalk ideas and closures was revolutionary by the time and many programming languages picked up on this concept. I'm exploring Go right now (mostly because of Ken Thompson participation) and it's clear that it's just slightly simplified version of C. And in this context the rants on C++ appear to me absolutely unjustified. It's quite old language, for sure, but we have to acknowledge the fact that we haven't created any language that is ready to make it a history.
Totally agree. Still, I think 90% of C++ features are just useless and plain dangerous to use. While it is true that no one is forcing me to use something I don't need, often at work this does not apply. There will always be that mf colleague that will pour nonsense C++ sugar syntax in the codebase to do what a memcpy would've done just fine. Freedom is beautiful, but too much is just plain chaos.
The part on tuple was enjoyable to me... I'm working with Python right now, and I'm so sick of tuples. So much values everywhere, and I don't have the slightest clue what half of them do ! I would also agree that out-parameters aren't a great pick. I rarely use those myself. Because I believe defining a struct for the return type and instantiating it with brace initializers is the best way to tackle this issue.
In Julia they have something called NamedTuples, you can give names to elements in your tuples, and you won't forget what they are. No need to define a struct just for that :)
C++23 will provide the modules std and std.compat to solve that issue, let's hope that in the future new libraries created with modern C++ will use modules.
@@gagagero All three major compilers have module support. GCC is almost completely compliant with just two papers concerning some issues with the initial drafts of modules not being implemented. Clang is compliant to a usable state but also has a few edge case issues. MSVC is fully compliant. But yes it would be nice if Clang and GCC also were fully compliant but that will probably still take a few months
I honestly like c++ but I haven't ever made a bigger project so I don't think my opinion matters much. I literally have 3 repo's on my github and I'm proud of only one of them. (1 from when I was learning pure JS alongside HTML and CSS, and 2 made in C++)
Bjarne Stroustrup is brilliant. All that crap implemented on top of the existing C language with syntax and symantic backwards compatibility (mostly). And templates are still the most powerful generic, yet not always the easiest to use.
If you do bad things in C++ it compiles, it runs, it segfaults. If you do bad things in Rust it doesn't compile. You cannot make that skill issue argument equally, no. A wrong program not compiling is better for bad programmers (and good ones alike) than it failing during runtime. To sum it up: Rust is better.
While I do like Rust, there is an argument to be said for getting code to a working version faster. The thing is that C/C++ does let you get working code faster. So long as you do it right of course, you don't have to bother dealing with annotating lifetimes and all that. The danger of course is that if you do screw that stuff up then you're going to have a bunch of very annoying debugging problems.
It depends. There's nothing for Rust comparable in quality to C++ static code analysis tools. Rust gives you a better baseline safety for free, but for really high stakes safety it's not ready.
Call me crazy but I love c++. The main thing I like about c++ is that I can choose how much abstraction I want we where and in many cases I can use abstractions without sacrificing performance. I also like being able to do the dangerous low level stuff manually if I really want to. I do hate having separate header files and source files so I just write the implementation in the header file. Sure it's going to make compilation take a bit longer but soon I'll be able to easily convert those headers into modules once they are better supported.
@1:10 std::sum is a thing, as is std::accumulate. and std::transform_reduce. And std::reduce. And std::partial_sum. And std::inclusive_scan and std::exclusive_scan. I mean how many different ways to sum a collection do you need? Why does this guy complain about c++ without knowing what the STL can do for you? std::for_each isn't everything. Although that, too, can be used to sum a collection. @1:27 what is first class support supposed to mean? std::tuple is a thing. The heck is he talking about? It even has variadic template arguments for a tuple of arbitrary length. And if you want something else, try std::vector if you want to be disgusting. Or make your own class. It's not hard. There is even structured binding to unpack them nicely. ```c++ float x{}; char y{}; int z{}; std::tuple tpl(x, y, z); const auto [a, b, c] = tpl; ``` @2:00 oh smart pointers are slow? Have you measured that? std::unique_ptr is extremely simple and well optimized. It barely costs more than new and delete and for most systems the assembly instructions are even equivalent. There is literally no performance penalty for them. Since unique pointers are sufficient 90% of the time, they're just plain better to be using. As for shared pointers, yes they are slower. But who really cares about a few nanoseconds? Do you really need to optimize THAT part of your program? I'm sure there are better ways to spend your time. Go to godbolt right now and plug this in with -O1 or higher. It literally produces the same code. ```c++ #include extern void f(int* p_i); auto main() -> int { int* p_i = new int(31415); f(p_i); delete p_i; std::unique_ptr up_i = std::make_unique(31415); f(up_i.get()); return 0; } ``` @3:00 C++ is a great language. It's low down and hands on if you want or need it that way, and as high level as you want with many great libraries. The problem lies with how people are taught c++. You don't need to know arrays, pointer arithmetic or bit shifting. Don't teach people cstrings in char arrays and printf. They don't need it, and it makes them worse programmers at worst and at best it discourages them and makes them think c++ is hard and they can't understand it. What they need to know is STL, data structures and the modern types like string and vector. Teach them how to write useful classes, not variadic functions. Teach them how to structure code with classes, structs, namespaces, enum classes, not how to write c programs that compile in a c++ compiler where you have to shove everything into functions in a global namespace and then have to come up with weird names. In short, stop teaching C, that's just baggage that you will never need to use. There almost never is a need for using new and delete. Raw pointers are fine as function arguments. Unique pointers get you 99% of the way where you need to go. shared pointers 0.9% and the rest you have to use weak pointers for. Almost any data manipulation, query or restructuring that you could ever need is covered by the STL. And when modules release with c++38 they will have fixed those horrible compile times, too. What tripped me up is the weird build system. But once I wrapped my head around compilation units and the fact that templated functions and class members aren't actually real functions and need to go into header files, I was good. C++ has a reputation for being difficult, but it really is just a matter of perspective. I know dot dot dot is where the fun begins, but I never had to deal with that. That library writer stuff, and I don't write libraries, and when I do they are simple enough to not require variadic templates. @8:55 I agree. const should be the default, but it isn't. clangd does mark pretty much all the places where you can make things const though. It was a bad design decision made ages ago. but they can't just change it. I've learned to live with it. And constantly thinking about whether a thing should be const or not also helps in a way. That said, a lot of languages don't have const as default. python doesn't even have a const to begin with. or private members for that matter. c# has readonly and const, neither is default. javascript const is non default, but javascript sucks anyway. java doesn't have const as default. actually there are very few languages that I can name that have const as default. probably because it is annoying. you make a variable to mutate it. it's in the name. a constant is just a name for a value. You can make `this` const by declaring the member function `const`. You think about that when you design your class. Does this function need to change any class members? No, declare it const. It's not about the this pointer, it's about the function. @13:00 I agree. copying can be slow. Just consider all your constructors for all your classes and you'll be fine. A class that is correct with all of them = default is just the golden medal. If you don't want your class to be copyable, then that's fine. What's the problem? Alternatively make the copy constructors deprecated for a warning to the user if it is probably a bug, but not necessarily a bug and let them pragma out the warning and explain their actions if they need to copy. @13:30 bad. don't use references to modify values. references should always be const. If you want to modify values, pass pointers, or use a return type. make tuple is hardly long winded, especially with template argument deduction. using references obscures the fact that you are changing the data. The best way would be to either name your function in a way that strongly suggests that you are changing a parameter, or return a data structure of some kind to hold the return values. @15:00 and there is your problem. You are writing c code. what the hell are you doing needing to pass sizes and arrays around? the message should just be a vector or similar. let the vector handle the hard stuff like allocation. buff should contain it's own size and be dynamically allocated as required. @15:30 use gsl::not_null
Sum types means something like std::variant, but good, with pattern matching. It has nothing to do with std::sum; it’s a term from set theory. First class means in the language rather than in the library. It’s my gripe about what I find annoying, and std::tuple and std::variant aren’t up to my standards.
Funny where I work we also have non nullable versions of smart pointers. They can not be initialized as null pointer, but they can be moved and after move the non nullable smart pointer is null, which renders them kind of useless and already caused a few crashes.
other programmers: this is an int c++ programmers: i'll make this a typedef just in case i want to compile it for a 42 year old CPU other programmers: this is a string c++ programmers: thank god i don't need to typedef this because there already is a typedef of a typedef of a typedef of a typedef of a typedef just in case we need to run this cloud database driver on windows 1.0 or the apollo 11 hardware.
rewrite this message in 42 years, when your program has been written to run on a 42 years old CPU and sadly never got updated because one client keeps to say 42 years old CPU are the best and they pay for it
The non-nullable owning smart pointer can't be moved from because what would the value of the pointer be after you moved from it? The obvious answer would be "null", but, it's non-nullable. You're breaking an invariant if you do that. And one of the rules for move (a style rule, but this is a rule, not a guideline, your code is broken if you don't do this, even if your compiler doesn't tell you) is that the moved from object must still be in a valid state.
"You're breaking an invariant if you do that. " Yes, but you could have it set so it throws on access so that the only valid operation for a nulled pointer is the destructor call. IMO the policy of making the moved-from state "valid but unspecified" is a mistake.
The more I use C++, the more I love C. I just don't want to worry anymore of some hidden behavior of my code: if I write C code, I am sure of what will happen and if a copy will be made. C++ hides stuff that I want in plain sight to see if needed. Headers don't bother me much, I just use them as interface to the outside world. Disclaimer: I work in robotics embedded systems.
but if it's your own code base you know where the hidden behavior is so why is that so bad? Not sure which hidden behavior you're referring to though...
@@jordixboy C++ isn't that complex either, but teachers and books tend to overcomplicate it by throwing an entire lexicon's worth of OOP theory at you.
@@HairyPixels I would say that if you are the main contributor and know 90% of the codebase, you would be fine with every programming language. However, in a company usually you are not alone. When working with many engineers, it is very hard to force a coding style upon everyone, and since C++ allows very different programming styles, this leads to a mess very quickly. Freedom of choice is a good thing, but too much freedom leads to chaos. Just my take on personal experience.
That's not how header files should be understood, they are required by the compile when objects are to be linked, ideally you wouldn't want to recompile every parts of the glibc at each compilation, header file only define the signatures, structures and symbols that have been implemented in the glibc. glibc is then linked by the linker when your program is compiled. Most people think of header files as libraries but it's not that, you can find single header libraries where the source code is in the header itself, this approach is fine for small libraries, however it quickly slows down compile time, why would you want to recompile the same module everytime you make a change? Header files are also the literal foundation of bindings, any language that want to allow other languages to bind has to be able to create an object file, and an equivalent to a header file somewhere so that the linker may still know what its dealing with....
13:47 this is wrong as well at C++11 and up if you mark the return type tuple your can literally just for example Tuple return { a, b }, this works for structs and classes as well. C++11 you would need std::tie, but C++17 has destructuring.
7:20 Do you really need multi-pass compilers for that? Just presume the identifier exist. Error some other time. I'm sure that's more complex but the ergonomics of not needing redundant code for basic features of the language seems worth it. Consider the multiplied effort of every user of the language vs the implementation cost.
But you need to still know what the identifier is declared as, not just that it exists. Maybe you need to implicitly cast an argument, maybe it has default arguments you need to put in, etc. So unless you go ahead and parse the source files for every compilation job separately, multi-pass is a reasonable method. Or implicit "header" files that get updated with the source file on demand.
Tuples are bad if you're "using them wrong". What I love doing in Rust is just destructing the tuple once I'm using it. Then bundle it back up if I need to. And yeah, if I need a particular tuple a lot, then it'll be promoted into a struct.
Tuples should only be used in (highly) generic code imho, otherwise just make a struct with named members, so much more readable. I barely ever use tuples/pairs, and I do write somewhat generic code from time to time.
Tuples are mainly useful for whenever you need a function to return multiple values that aren't specifically related in any way and are expected to be split up immediately on being returned.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
19:00 That C++ does not break/remove stuff is patently false. Examples I can name without looking up: auto_ptr (deprecated in C++11, removed in C++17), _constexpr_ implies _const_ for member functions in C++11 (thankfully immediately removed in C++14). For the standard library, there is a list on cppreference “Symbol Index (removed)”.
Holy crap, member functions can be constexpr? That would mean the object that calls them is also constexpr, then? And where would that object be declared? In what order would all that code be executed at compile time? It's mind-boggling.
@@ruanpingshan A member function being constexpr means it can be called in a constexpr (member) function. The object can be mutable. There's loads of documentation online. It doesn't mean that much, honestly.
"And the header files still have all the private members of the class inside...!" IMnHO, THIS is the most horrific fail in C++, on par with simply having to wake up every day to program in either Perl or JS except as a matter of sheer survival.
And if you want to make a C++ wrapper of a C library, you still have to pollute your entire namespace with the C headers, because otherwise you can't declare private members using types from the C library. The only alternative is the ugly Pimpl pattern.
@@ElementaryWatson-123 The moment you include gl.h, you have every single OpenGL function, typedef and macro in your global namespace. That's namespace pollution. And making C++ wrapper classes is not an easy solution, because if your gl_wrapper.h uses any OpenGL type, then you have to include gl.h in gl_wrapper.h, and whoever includes gl_wrapper.h will get everything from gl.h as well.
Smart pointer can be lightweight in the form of a unique_ptr and weak_ptr or heavy weight in form of shared_ptr. The problem is to properly handle unique_ptr (e.g. as part of a vector or other classes) you need to have more fundamental knowledge about move(), release(), swap() and copy() / the copy constructor.
can't have a weak_ptr without a shared_ptr. unique_ptr should usually be what's used for ownership and raw pointers for non-owned. unique_ptr is just as fast as raw ptr. valid use cases for shared_ptr exist but they are the exception, not the rule. People just overuse shared_ptr.
@@KX36 Yep I have found one valid use of shared_ptr so far and I'm not even sure it was a good one (I used it to solve cache invalidation in a multithreaded context, that way things don't die immediately when evicted). Value types like vector are the thing I reach for first, unique_ptr second, and shared_ptr a very distant third.
I coded for agricultural, infrastructure and automotive industry. In this area C/C++ does an awesome job at tiny and custom ordered chips. But it's a completely different world of programming compared to anything related to web, cloud or desktop/laptop. Almost everything is fixed mapped in memory. You try to avoid stuff like an OS, garbage collection or networking at any cost as it only increases power consumption and system completely without providing any value to the user/customer. I agree to an extend on safety features and possible bugs. But we have a lot of awesome testing tools, we need full or close to full testing anyway. If you write a vehicle or flight controller there better be no bugs in it, or you go to jail pretty quick. In those kind of applications a "low feature" language is a great choice. But we do adapt Rust or Java for displays, and infotainment units. Anything thats more powerfull in compute and has no real command over the machine. It's also not uncommon to invest the effort and optimizing stuff in assembly. Even tho i tapp out of the projects at that point. I only put physics i to C/C++ code and make sure the physical machine acts like i thought it would.
Story from a senior. We used to learn PASCAL. A STRONG TYPED object oriented language. Those who are excited about RUST should first learn OBJECT PASCAL. This language is like 35 years old and does TYPE CHECKING, BOUNDS CHECKING etc, etc. What is this silly hype about RUST. ... The C language was chosen and preferred because PASCAL was totally inflexible. C became the standard and later C++.
unique_ptr is generally, not slower. And so, while it's a smart pointer, it's not slower. There is a slight caveat. When you call a function that takes a unique_ptr, the caller still ends up having to check if the called function took ownership of the argument. But that is a very tiny speed hit, and only shows up in specialized circumstances. Now, shared_ptr, OTOH, is slower than a regular pointer.
A unique pointer isn’t but a shared pointer is a tiny tiny bit slower because you need to increment a reference count but reading an int from memory adding one and writing it back is 10 cycles. And that’s with a change miss. A clone in rust is a hell of a lot more when you copy more than one byte.
@@CallousCoder - That's not how unique_ptr works. unique_ptr is a very thin wrapper around an ordinary pointer. You are accurately describing how shared_ptr works though.
@@IllidanS4 - No. That isn't an issue, except possibly in some very strange circumstances. If you are using the pointer by value (not a reference or a pointer to it) then the compiler has enough information to completely optimize the destructor. But, it may be an issue if you are pointing to the pointer. But that'd be an issue with an ordinary pointer as well then.
@@Omnifarious0 Yeah I just fixed my text 😂 and I saw your reply. I thought they were talking about shared pointers because that’s the only one you need to count references.
I thought it was gonna be a serious blog complaining about serious defects/flaws in c++ but it's just convenience issues. There is a cost to freedom and performance, and if you're too lazy and undisciplined to use it then don't. But don't complain about things that are due to your laziness.
As a C++ programmer this has made me interested in learning Rust... although the Rust foundation turned out to be weird. I guess there's a gap here for a better Rust.
Circle, Cppfront and carbon all looking good. Swift has good interop with c++ now so could actually become successor if not only apple controlled most of it
Exactly . Never tRrust the Foundation. The same people are still lingering there since the logotype debacle. What will they come up with next? something like Redhat, HashiCorp or Oracle ?
@@kevindelnoye9641 Swift is a very strange language though, with some baffling decisions. I have my gripes with Rust but nobody can deny that at least it's a solid core that solves what it set out to solve. Swift is filled with things that make you go "buh?" like the lack of const for classes and that awful syntax for callbacks.
Rust was made by learning from the mistakes of C++, Haskell, Java and others. If the Foundation is going to kill Rust, there will likely be a new language based on Rust's features. You can't waste time if you learn something new.
The real fail here is that this guy claims to be an advanced c++ teacher but doesn't know that the language already provides a "non-nullable unique pointer" option as a first class part of the language.
@@steffahn Granted, it not 100% parity of features, but its 99% of what people want with a unique pointer. The whole reason why the smart pointers exist is to provide automatic cleanup and to give ownership semantics to the language. If you take your arguments by reference and by value, you are signifying owership semantics. Whoever created the initial variable, that they are now passing by reference, still own it. You cannot take ownership from them. If you wish to pass ownership, you can pass by value and std::move to make your transfer of ownership explicit, even if its just symbolic. Any cleanup will happen at the appropriate time. I assume we don't need to discuss the non-nullness of references in c++ So what, in your opinion, is missing?
@@khatdubell I have only watched the video once, but from what I remember the author's point was that things aren't properly expressed in function signatures (nor documented, since people don't document shit). I'll agree with your trade-off: Non-null pointers do exist in the form of references, and I think references in C++ are a great feature. But if you write a reference into your function signature, this signature isn't expressing that the function requires uniqueness - for example two parameters could be the same reference. Of course you can document such additional requirements, but then again, you can also document that a unique_ptr argument isn't supposed to be null.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
The C++ experience is like when your stomach grumbles for hours but when you finally get to the restaurant you realize you've entirely lost your appetite.
Moved-from unnullable smart pointers can just be put into an undereferencable state (that is most likely internally null). They're still very useful. And if you find yourself having to implement destructors or move operations in high-level classes, you're doing it wrong. Write low-level resource management wrappers, compose your class of those and let the compiler generate the special operations for you.
@@romangeneral23 You don't have a clue what you're talking about. 99% of the internet is powered by linux servers. How much C++ is there in linux again? Oh yeah, none.
Someone in some other comment said the major compilers already have support for them, with clang missing a few things, gcc a couple edge cases and msvc being complete. No idea how right that is, but maybe it won't take that long
@@user-sl6gn1ss8pcmake has basic module support (still experimental I believe), meson is still trying to figure out how to bake them properly, and dunno about bazel. I would guess modules will be ready to be used as of cpp26 release
I attempted to write my toy debugger in Rust a few years back. It was after that I realized that Rust is not amazing, at all. Lifetimes leak into every single thing - and everything becomes a chore of leaking the life times (to 'static) because you *know* the life time is ok, but the compiler doesn't think you know. So you use unsafe. For a project like a debugger, that would involve wrapping the _entire_ code base in an unsafe block. That certainly is not great. Or amazing. Or developer friendly. On the contrary, for that domain, Rust makes you think about _all the things you DON'T want to think about, because you actually don't NEED to think about them_ - so that argument works for Rust as well. But now, you have a compiler that _thinks_ that it has resolved it to be true, that there are no aliasing going on - and boom. Foot-gun-fuck-land.
I vomit inside every time someone calls rust safe. Its not safe, you just haven't done anything non-basic with it. Even without using unsafe, i've managed to unleash monsters. The only reason people think rust is safer than C++ is because those people don't compiler their C++ with warnings turned up and promoted to errors.
Lifetimes leaking into everything is usually a 'skill issue'. I had exactly the same issues when I started out, the solution is to use the right design patterns to store your data. Knowing when to use a handler or arena, knowing when it's okay to just do a deep-copy and eat the minor performance loss, and when to use Rc solves most of these issues. It's a real hurdle at first though if you're not used to it.
@@khatdubell >Even without using unsafe, i've managed to unleash monsters. Could you explain? I'm super curious about safety issues in Rust. I know that at least one of them exist (since it's a Clang bug which the Rust team can't fix), so I'm wondering what you mean otherwise, or where you got undefined behavior issues.
@@Mond-mk7tkI've run into several issues, but its not like i've written them down. The latest one, and this was like over a year ago now, was a threading issue. Again, no unsafe code blocks, and the compiler "OK'D" everything, but i had a runtime error That's about all the specifics i can remember at this point. Sorry.
@@Mond-mk7tk I don't think you understand the domain I'm talking about here. The data that the debugger manages is fine. But unless you want to do a *bunch* of copying of binary data, that has debug symbols encoded in a binary format - you must leak the life times. There's no way around this. And that would be abhorrent, for a debugger to do. Especially when debugging a non-trivial application like Firefox, which has 2+ GB of debug symbol data. In this case, Rust's idea of life times break down - and I've seen the libraries written to handle DWARF; they all use the leaking of life times, because otherwise, it would lead to more insanity and rigidity of the code. Rust is not great for everything, it simply isn't. No language is.
Making Breadth First Search in C++ was easy, in Rust how ever it was a no go for me. I did not work out the life time things (since pointers are a must for this to not take up GigaChads of memory). I was curious about the speed of Rust compared to C++ using the same dataset for BFS. I also wrote and tested Go and Java versions, both very slow. Probably due to not using pointers.
What you mean by very slow? 2x, 5x, 10x slower? How exactly your graph representation looks like? I remember playing with similar stuff and Java was about 2x slower only
Almost anything involving graphs (especially undirected and with cycles) seems like a real pain to implement in Rust. I've even seen people in the community recommending unsafe Rust for graph data structures.
I mean I don’t like that fact about C either, but at least C isn’t pretending to have good abstractions while actually making things harder. I can prefer C to C++ and dislike things about both of them. Preferring C doesn’t mean C is perfect…
@@jimmyhartzell4361 you can use only abstractions that work well for you. At least smart pointers, function templates and stl algorithms are ok, why discard them altogether?
C++s sum types (std::variant, std::optional) are practical, but they aren't real sum types, and it's very difficult to make them so. In Rust, is there an empty type? That is, one that cannot be constructed? The effect should be that for the empty type 𝘌, if we have 𝘱 of type 𝘌 + 𝘈, for any other type 𝘈, then 𝘱 is guaranteed to hold 𝘈? (Yes, I know many programmers would ask “what's the point of that?” It's a math thing, and it does turn out to be useful for reasoning. It's like having the number zero in the integers.)
Not exactly the same thing, but in Rust a function can return "!", which actually means it never returns a value. Think about an exit() function that aborts the program for example.
@@MI08SK This is very true, and something that several people in the ISO C++ committee have been working on for years. It is considered a priority for the next standard release (C++26, I suppose). But I know, at least, Michael Park has been working on it since at least 2016, and had something working 2017, so ti's taken a (rediculously) long time.
6:55 You may like it or not, but it makes perfect sense. for larger projects, library components and APIs. Why on earth would you want to know the specifics of a function at compiler time? How about libraries and system calls that you don't program yourself? How about module/library interfaces where you only want to expose a minimal set of functionality and abstract its inner workings? Do you think a compiling a separate module should also have to deal with avoiding symbol and namespace collisions from every other module in your system? Do I NEED access to the full source code of the C++ standard libary's just to compile a program? Isn't modularity and replaceability a major goal in software engineering?
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
unique_ptr literally generates exact same assembly as doing a raw pointer correctly. And shared_ptr generates the exact same assembly as doing a shared pointer correctly. Except for When const is the default.
13:46 hard disagree with the take. "out" can be pretty useful if you relegate it to functions like TryParse and any other function which may conditionally fail to return a value but uses a boolean return to represent success so that you can easily throw it into an if with a local variable that is only scoped to it being valid. A great idiomatic way to avoid coding in exceptions imo.
Years ago I was about to proposed on cpp-moderated, how string-literals can be arguments of non-type templates. It was highly requested and would have enabled things like type-safe print (std::format) etc. in C++11. I've implemented prototype in gcc and clang (only gcc patch was public). It was really simple change - like 20 LOC, but 1000's in tests. Then I discovered that hell will brake lose due to mixed (wide/narrow) literals concatation. Never decided write this proposal for that reason. It would have been extension to C++11 variadic templates and author of those already agreed present it for commitee. Btw. similar defect was discovered with user-defined string-literals in about same time. It is really really hard to extend this language. But there is no way to push Rust to degree we sometimes have to do with C/C++. And when we do it, that code is messy and tricky for all other reasons than language. So, no. Rust or any other safety oriented language won't do the trick in most cases.
duh C++ is literally 40 years old and built over on C yet someone who just existed yesterday moans about it cuz compared to modern times where everyone can write decent compilers if they want, lot of tooling & resources, variety of languages, a LOT of software engineers resulting in a bigger percentage of testing & creating much better software. Oh no C++ has this & that ? bruh the standard ain't breaking things to satisfy your ideal ideology of a language. The paths to make C++ better is by either improving it adding more features and teaching the modern C++ extensively to overcome the stupid misuse of the language or create a successor to it sth like kotlin or swift that's suitable for modern days unbelievable standards
To all beginners. C++ learning curve is absolutely brutal. It's not even linear, it's a fucking 2^n curve. Even I took C before C++, I still open the damn docs back and forth.
Why is that a problem? The choice of default non-const is actually the right one. It's more often than not variables are non-const than const. If someone doesn't understand whether something should or should not be const, they aren't skilled programmers and usually compiler will stop them. There is no difference from the point of view of safety which default is used, people can be just as profligate with mutable as they are with const if they are not proficient.
"I don't know anyone other than game devs who say c++ is a great programming language" as a game dev, I can't understand why anyone would want to write anything but c, c++ or c# xD
hey man, I'm pretty good at python and built some games in it, but now I wanna try the real stuff and start building with unreal engine. I can dedicate 6 hours per day to learning, researching and building with C++. How long do you think I can become good enough to be hireable by a big studio?
There is even bigger problem with c++. It's the newish introduction of build tools that break everything in c++. Try build something with android and you notice that my 222kloc project cannot be modified any longer since every modification to a header file requires full compile taking 2 hours. Its build tools like gradle, cmake, ninja etc that cause the problem by insisting theorethically correct dependency graph, but when my modifications always modify both .hh file and .cc file together in single transaction, compiling 300 .cc files when compiling just one .cc file is enough for incremental compile is just completely crazy decision by the build tools. When taking plain makefiles into use and noticing that you can actually modify the code is such a nice feeling....
I might be wrong 11:44 I feel like he's just doing something fundamentally wrong he, he complaining the structure/class isn't abstracted to a movable reference for him that that has to be done explicitly in C++, sure it would be nice to have some syntactic sugar for this but his solution seemed to be convoluted. And overriding the default methods unnecessarily, he should have been using a unique_ptr and moving that around to be fair the move still isn't implicit but you would have the std::move feature he wants without having to override default methods and have the other issue he had.
C++ is not going away anytime soon. In fact, no language is obsolete other than a very few considering how we define obsolescence in general. Rust? Zig? These languages will also have their niches. Computers in the distant future (within 30 years) will be radically different than what we anticipate. Analog computing units might make a comeback. AI is becoming mainstream. Governments are becoming interested in crypto. People like us who are either hobbyists or professionals might have to look elsewhere. I mean, parallel computing, HDL, VHDL, Assembly, etc. Then, there come field-specific languages like Mojo Python for AI, C++ for crypto, C++ for graphics, C for embedded systems and such. What language will be the de facto choice in quantum computing? People still do not have a clue. If fatty multinational corporations like Amazon and Google start leasing out quantum computers to common people, forget any leisure you'd have. 👍
Quantum computers are going to be very limited. This is largely because quantum algorithms themselves are ridiculously complex, so there just aren't many of them and they're not something an average coder is going to come up with on their own. Making quantum algorithms is basically a separate branch of math in itself.
No, digital computers are here to stay for your entire life time, simply because of one reason; relyability. Only digitial systems are reliable. This implies that C is also here forever to stay as the fundamental way of (relyable) computing won't change.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
If I may share my thoughts, with all that high complexity of classes with the need to implement all those copy constructors and things and how easy it is to forget them, I now believe with C++ it is far more easy to make mistakes and accidentally introduce undefined behavior and crashes than it is with the simple C language, even though C does not have smart pointers or any RAII solution. C has always stayed a simple language, and that aspect wins out. In that way I also believe that Rust is especially a replacement for C++ even more than for C, even though people mainly compare it to C and talk about that a lot.
Like it or hate it, C++ is still the de-facto standard language for doing so many high-speed real-time demanding applications. Take the world of making plug-ins for DAW applications, for example. Things like softsynths, samplers, reverbs, delays etc are all done in C++. Same with game-development. And mostly the same thing for Operating Systems. And embedded systems. Yes there are other upcomers that are just as performant but they simply aren't the standards for doing these kind of things. We may swear how much we want but it still ain't gonna change this fact!
@@Asdasxelc++ is still used, bjt that's true C (and asm) is the king of down to hardware code. c++ has to be stripped of some features to do so, but can still very well run
Indeed. For game development, the only language I can replace C++ with, is Nim. And not currently, only after they implement cyclic imports (which will probably happen this year or early next year). I can't wait for that, so I did a little hack to achieve it.
As a hobbyist C++ programmer of 15~ years one thing that annoys me in C++ is the many different ways to define a type. I dislike also that a struct and a class are the same except that one is public and the other is private by default. I think I like Java's public and private denotions better.
There are a few things like that, which think just come down to backwards compatibility. Can use one and forget the other exists, or as a personal way to distinguish class and pod. I like to use structs only, with functional techniques while pretending cpp isn't object oriented.. Freedom language.😄
I don't think that languages like Java or C# are better in terms of encapsulation and information hiding. Actually I like the concept of splitting the interface/definitions in header files and the implementation in c or cpp files. Java and C# put all into one file. This is a hack beyond belief in my eyes. The only thing I regret in c++ is that you are forced to set the private section of a class in the header file as well. It doesnt make sence to me. Why have the client see this? It is not part of the interface. Oh yes, you can do tricks with the PIMPLE ideom, but this has its own drawbacks: You are forced to allocate your implementation object on the heap (at least I didn't find a way to implement PIMPLE without the heap).
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
All you have to do is read comments in HN on posts or comments that state or hint that C++ is imperfect:, and you'll see it. "C++ is fine, you're just not good enough for C++" (with the implicit "like I am").. Somewhere in my stack of long-unread books is a Sams intro to C++ with cover art that has a green lawn with "C++" cut into the ground, revealing hellfire and brimstone: a perfect metaphor for C++, the Borg of programming languages.
like to see mention of the way in which you can use c++ like rust with unique ptr and union types. I get that they are in rust with syntax but so many people talk like they are new ideas never seen before lol
Here is what he and you both seem to not realize. There is code written in C and C++ that was written 30 to 40 years ago that is still working and running today. You are talking every major OS system having to be rewritten if you got rid of C and C++ backwards compatibility. Most the network communication industrial controls for chemical plants, reactors, and so much more. But it doesn't just come down to the actual work of rewriting all that code from scratch you have to retest all of it. It has to work on the hardware some of which is old as hell. I've seen Muxes, controllers and other systems decades old still in operation. That means for all that hardware you would need to write new compilers for each and everyone of them and ensure no bugs exist. What a bunch of people who complain const isn't the default is going to do that without breaking everything. Yeah right.
Honestly, all you really have to do to clear out the vast majority of C++'s actual footguns is use a static analyzer and Valgrind. Add in some good testing - which you should be doing anyway - and you're golden. It's not hard. We have the tools.
19:37, this next point is something I'm planning to solve with the PATH environment variable, let's say you built an app for the 1st version of the library I'm making but the library has since advanced to version N. Rather than make you update the app the user would instead be required to launch the app with the correct version of the library bound, for example: > paw1 --start app ... app ... > paw2 --start app ... error app not found > paw --start app ... error app not found paw1 shall always map in version 1 of libpaw and the related directories, in this scenario the app can expect the entire ABI of libpaw to match that of the 1st version and any libraries that the app relies on besides libpaw to likewise rely on the same version of libpaw. When paw2 is used instead the attempt fails because the app is not in the libpaw2 directories and thus not mapped in via the PATH environment variable. As for the final example, paw shall always map to the latest version of paw (in this case paw2) by default, there will be 0 need to maintain old APIs between versions (besides the possible scenario where there's no need to change them, buffer functions for example). The 1st version of paw (paw1) will expect *.exe apps since wine can be used elsewhere to launch them, this simplifies the build process since you don't need to do multiple versions of the same binary (which would defeat the purpose of paw, to eliminate native programming as the default programming paradigm for C/C++/C#/Obj-C and instead make fully cross-platform programming the default. For the ABI issue there will be separate directories for each ABI so there's not even a need to check against the back end of integer types like pawjd which by default maps to __INTMAX_TYPE__ (paw will insist on GNU compatible binaries so only GCC, Clang, etc are valid for compiling with). For intmax_t there's a whole bunch of crap apparently that goes on at the back to maintain ABI compatibility between x86 & x86_64 binaries etc. For paw this is not even worth considering since the binaries simply don't get mapped in if they're not matching the current ABI so paw is free to break ABI compatibility as much as it likes between directories so long as the API remains the same for the version it's mapping to. Likewise because of those directories there's not a need to maintain API compatibility in the future if a compelling reason to drop/change it comes up (like security issues) so the compiler will be able to catch these differences and force an update of code where it matters.
@@Robertoclos-ib7cc wtf? God DOES exist, he is information itself, every bit of light, sound, etc that comes at us is just a representation of information that already existed before we were even born, before the universe even came to be. To deny God is to deny your own existence, it is to declare whole heatedly you are of the biggest fools there are on earth. It is the same as declaring you can't look beyond your own bubble of senses to what lies beyond time and space. Until you do you will never find God in this lifetime and in the next it will be far too late for you to find salvation for your soul, to find pardon for your offences against God (like the one you just committed). Lord knows I'm not worthy of him either but that doesn't change that he went to the cross in human form (Lord Jesus Christ) for ALL of us. He endured the price you will likewise endure if you do not refuse to acknowledge God as your Lord and trust HIS ways, not the ways of the blind like all who treat MAN MADE "gods" as as anything more than simple idols that need to be abandoned. At best they're simple entertainment, at worst they're devils of satan deceiving the masses.
Want to return more than 1 type? Use structs. Everybody says tuples, but I have seen them being used only in the test code. Besides that while agreeing that C++ is not beginner friendly, most of the things here are minor stuff in my opinion.
As an ex basic(s) ex pascal ex Oberon ex java ex js ex ts ex Erlang ex lua ex c ex fortran ex Haskell ex prolog ex clisp ex python c++ dev, h files are not that bad if you keep just your pure set of interfaces in it. U r holding it wrong. Repeat after me: only std lib, templates and pure virtual interfaces in headers! Also, just have factory classes/static functions in the interfaces that only return sh ptrs of the said pure virtual interfaces! All of this goes away!
Wait, can I do that in C? I got to give it a shot. What do the C files look like though? I guess you treat it all like mini modules with mini interfaces
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
Languages are imperfect, but you can learn a subset of them and patterns in them that are reliable, then focus more on the interesting stuff, that is, what you're coding and not necessarily how you're coding.
9:00. Where I work, const has been in the linter so long, that it's ingrained in us to use cost by default. Except it's JS, so it's not a const const. We haven't switched to DreamBerd yet, ik ik.
don't listen to this people : D if c++ was bad they wouldn't use LLVM to create rust crap language . all rust is based llvm and gcc and those are written in c/c++ XD this people are out of their minds . rust compiles the same code c++ does cause its all written in c++ it just rust doesn't lets you to have freedom to shoot at your foot XD .
@@Phantom-lr6cs No. The reason Rust uses LLVM to optimise it's output is because of the work required to replace it. They're using the "if it ain't broke, don't fix it" methodology. Just because a tool written in a language works doesn't mean the language is good. C and C++ are old and crufty. C is still fine because it's super simple. The problem is these languages are awkward to use because they don't have the modern niceties. They often got the defaults wrong. There are languages to replace these: Rust is a C++ 2.0 Carbon is a C++ 2.0 Zig is a C 2 Odin is a C 2
in rust you have a borrow checker
in c++ you are the borrow checker
What about C?
@@bresent Same, you are the borrow checker.
Cpp as of C++17 has tuple destructuring which is way nicer than using get or .first .second everywhere
yeah there's been a rather fast uptake of C++17 so bashing C++ because of tuples is rather ridiculous at this point in time
Structured binding? Which also has a little footgun attached to it, that it is harder for the compiler to do return value elision.
What about .threehundredfiftyseventh?
@@Robertoclos-ib7ccIn the name of the Spaghettimonster, i invite you to worship the Spaghettimonster alone: I bear witness that there is no god but the Spaghettimonster, and I bear that your Dad is the messenger of the Spaghettimonster. These words make you a servant of North Korea.
@@TanigaDanae there is copy elision and return value optimization, which one you are talking about?
In Rust you fight the borrow checker, in c++ you fight the entire compiler, the standard library, the build system in fashion this season, the human laziness, and at least 80% of the c++ commitee all at once.
but the joy when you win though...
@@KX36 you think you've won, but the real guerilla war is only starting. With UB behind every corner, and memory corruptions scattered in the most unexpected places...
@@KX36When???
In Rust you fight the borrow checker, in c++, you fight c++, all of it.
@@KX36winning in this case is only an illusion.
So I've been using C++ for many years now (tho I'm not a dev by trade) and all of these papercuts that he's listed, aside from the `const` papercut, were things that you have to be *taught* wrong in order to do it wrong.
How is it not obvious that `=` is *always* a copy? You read one page of a C++ for dummies book and it will tell you that with `=` you copy a value from one place to another. It doesn't say "move".
Also what kind of abomination is `void funct(const char void* mesg, [...])` who dropped this man?
Knowing something intelectually and keeping it in mind in everyday work are two very different things.
A lot of people will come from a reference counted language like Java or JS and in those because you're actually only passing around pointers/reference when assigning things, it seems like = is a reference not a copy.
@@anlumo1
True, but where do you put the line what someone has to know and what not?
I think there are at most 5 people on this planet that know every thing about C++, but there are some very very basic things every one who writes C++ code (and is not an absolute beginner) should know about. And assignment is one of those things. And 'because language X makes it the other way around' is not an argument but a distraction. Because FORTH uses UPN the way C++ makes calculation is bad and should be changes! :)
I really doubt that someone who is talking about smart pointers doesn't know `=` always copies. Also wasn't that entire part of the article basically about how implicit copying is default?
I assume the void was a typo, that parameter type won't even compile
Thank you for putting my pain about c++ into words.
Can you make an overview of cppfront pls?
you could have better spent that money buying a good C++ book, which would have alleviated your pain caused by illiteracy.
@@ElementaryWatson-123 🙂
When a comment section full of javascript developers try to grok what's so great about c and c++. lol.
I'm a c++ dev and really I disagree with this man. For me, the biggest problems are :
- Optionals and variants are not first class citizens (meaning, you cannot at compile time unsure that the content of the object has been check before unpacking it (see Rust and Zig for this type of things))
- inheritance is just pure pain, I am good with the language, I can understand most template wizardry etc but the moment you throw multiple inheritance in the mix, it is hard to get what is going on and I have to travel between multiple files to get it (just a stupid way to make your code obscure).
- exceptions are a mess, like the const keyword, c++ has a noexcept keyword, which a few devs might use, but then nobody does use them, making it a pain to know if you have to catch something and most often, you just never try catch anything and hope that your test may tell you to use one.
I hope optionals and variants will be practical when c++ will get pattern matching
That last one is a pain point of mine.
It’s also risky to declare something as noexcept in a large project because someone will violate that contract.
On balance I think violating noexcept is worse than not adding it in the first place.
Needs more work!
@@khatdubell to be honest, I just try and return value errors like in C. It's not very readable but at least the error is contained and not propagated to god knows how many calling functions.
Isn't multiple inheritance a big no-no?
@@DN-fr2ez Well there are people not knowing this.
Plus sometimes it's just not "multiple" inheritance but "inheritance everywhere" which in my opinion os just as bad.
I trier going into some codebases just to need to jump to many places all the time.
At some point I just dread inheritance if it means getting code from parent class.
One abstract class from time to time, why not.
guys, I'm dumb. What the heck is "const char *void" (about 14:40 in the video)? I have never seen something like this before.
it's just a typo
ok thanks wasn't sure it was some cryptic K&R syntax @@bary450
Fixed in the article haha
Tuples are actually good as return types in C# since you can name the parameters instead of having to use .0 or .1. I almost never use "out" parameters.
A function should return one thing. Make a class for the return value if you need to. Narrower types are better and it communicates intent better. At least you're not returning a string tough. Good job.
@@FalcoGer I agree with you, but sometimes it feels overkill to create a class just cause you want to get back 2 things instead of 1, especially if it's for some private functions in a class which are called by other public functions in the same class - or to put in simpler terms, when it's a one-off scenario and the function would not really be called anywhere else or need that data passed around together.
The most common case where I'd return a tuple if it were a public function is say a function which queries the database or calls some external API, I could return an enum and an object. The enum indicates either success or a specific error in cases where there are well-defined outcomes (e.g. here's the data, or data didn't exist, or exists but you don't have permission etc, to save multiple function calls/trips to the database to first check those things), while the object is some nullable class (lets say a Customer object) which would be null if there was an error. Yes, to make it return 1 thing then something like a DatabaseResponse could also work which has the result and object. But again, such a function probably only gets called by 1 or few endpoints and don't have a need to pass them around together, so I just use a tuple, so I get back basically two "destructured" variables which I can give a friendly name like "queryResult" and "customer", rather than using "response.data" to get at the data. I understand this is just a style preference.
Yeah the tuples in C# are amazing
Yeah named tuples are fantastic.
Since functions can have multiple parameters, doesn't it make sense for it to be able to return multiple things ? @@FalcoGer
I don't know if I just had an insanely insightful professor when learning c++, or if I have just used it enough to get over the learning curve, but it seems that most issues with c++ come from people trying to write C code in C++. Yeah, it's valid syntax and will work, but that's not the point. If you "embrace the c++" and use the features as intended and not try to overthink it, I think you'll have a better time with it. Remember that performance and generics aren't the be-all-end-all and that sometimes using other paradigms, like functional programming, lambdas, etc., can be a very nice supplement to your C++ coding experience.
"I don't quite understand that"
unique_ptr is move only.
A default constructed unique_ptr is going to be a nullptr.
But per the rules of this new class he's talking about, you don't allow nullptr.
So you can't copy it into place.
Now, because you disallow nullptr, you can't move it into place.
The only option left is to pass it by reference.
Why would you create an empty unique_ptr? that doesn't even make sense... You should always use make_unique() anyway
@@insu_na correct. It can't be unique if it doesn't exist.
@@insu_na To pass the pointer, when you do a move in a unique_ptr the variable is left with a nullptr to guarantee that it is unique instead of having the pointer duplicated and later you can reuse the variable to assign it to other pointer.
@@insu_na Sometimes when you have a unique_ptr as a member in a class and are interacting with some C api you need to first set up some stuff in the constructor with that C api so you can't set the unique_ptr in the initializer list. In those cases you might want to make them nullptr temporarily.
@@insu_na
"Why would you create an empty unique_ptr? that doesn't even make sense..."
Well, there are, in fact, plenty of reasons, though i wouldn't label any of them as "good". People don't create empty smart pointers because they _want_ to, they do it because they _have_ to.
Something i've had to do on many occasions.
Secondly, welcome to the ethos of C++.
Its not the job or the goal of the language to decided the why's of what you may or may want to do. It provides the toolset, you provide the use of the tools as you require.
"You should always use make_unique() anyway"
You can use make_unique to make a defaultly constructed (null) pointer.
Unique pointers in C++ get completely compiled away and are only compiler safety mechanisms. Only shared_pointers have overhead and that is the minimum overhead required for reference counting (so like using an rc in rust)
“shared_ptr is slow” is a dumb statement without any additional context
That is almost true, unique pointers can add a bit of code to handle exceptions
Depending on the ABI, unique_ptr may not be zero-cost. ruclips.net/video/rHIkrotSwcc/видео.html
There's a talk titled 'There are no zero cost abstractions' which has a section on why unique_ptr can have a significant overhead in very special, high-performance situations and across boundaries? I recommend watching that part, very insightful.
unique_ptr in C++ must use the allocator (heap by default), some cases of compiler optimization can happen where the heap allocation is removed, but this is not the general case, they aren't compiled away.
Why are the complaints about C++ always come from people having at best very superficial knowledge of the language?
these people are clowns^3 XD
What's your point xD It only proves that this language sucks really early. The funniest Clowns are the C++ devs who think the language gets better with every version, but in reality the language gets more and more unusable because of all the bad design decisions. Just take Modules f.ex, until this date the most used C++ Version is 11,14 or 17. It will take multiple years until some C++ libraries will support modules and until company's actually allow the newer versions in their codebase. There is literally NO point in rewriting C++ code over and over again if we have way better alternatives like Rust, where safety and the really good type system come by design. Every C++ Game Dev I have come across, is entirely annoyed by C++. No wonder why nearly every game is a buggy mess if the codebase is C++. I'm really happy that C++ is slowly replaced everywhere possible. Google rewrites C++ Android Parts, MS rewrites Windows Parts etc. It will take some time, but the time is ticking for C++ and that is very good
@@ITSecNEO I invite you and other ignorant clowns on stackoverflow, all your complaints will be addressed.
@@ITSecNEO I invite you and all other 🤡🤡s on stackoverflow, all your inane complaints will be addressed.
@ITSecNEO you see, the problem is you don't look at facts but instead bring fanatism to the conversation. As of 2024, here is a small list of major desktop and mobile apps that still uses c++: google chrome, Unreal engine, Blender, Microsoft Visual Studio, Maya, Photoshop, Firefox, Autocad, WinRar, MySql, Spotify, Dropbox, VmWare, Tesla Autopilot software, Microsoft Edge, Opera, Safari, Unity, Adobe premiere pro, Amazon aws, docker, Whatsapp, Snapchat, Tiktok, and of course both major oses Windows, Linux, Mac,... Oh man i could go on and on. Wether you like it or not, c/c++ is everywhere, even on the device you are using to write comments on youtube, and the very core engine that feeds you this youtube video. So i don't know where you find your claims but it's not from real life.
1. I think the problem with std::tuple can be solved with structured bindings.
2. IIRC Herb Sutter is working on a new modern C++ syntax which transpiles entirely to regular C++. His transpiler is named cppfront, inspired by the cfront compiler which was the 1st C++ compiler which compiled C++ to C code.
1. we do have structured bindings in >=C++17 I believe, so perhaps or perhaps not.
2. thatlooksabsolutelybeautifulthankyouforsharingthatthat'ssogood!
1. Is addressed in the updated article in the description of the video.
Essentially, Hartzell's take is that it's a half-way fix because it isn't first class tuple support.
@@curlyfryactual it _is_ first-class, though. it's in the standard library. there's no need to add features directly to the language if the language is already expressive enough to express them effectively in library code. should filesystem access be in the language?
@@Spongman that does not constitute first class support.
Consider: being unable to use the standard library.
@@curlyfryactual if you're unable to use the standard library then you're not using all of c++. the problem is yours, not C++'s.
I remember learning about the copies back in 2008 - 2010 while I was learning c++. The book Accelerated C++ was really good at pointing this stuff out. They sure as heck didn't even mention this stuff in my college c++ class I took later!
Well this was dumb. What the hell is slow about a unique_ptr? And why are you using shared_ptr, it's a very rare case when multiple things own something.
C++ can be misused, yes, that's what reviews and seniors are for. Most of the things brought up, like out parameters can be solved by a sensible company coding policy.
I don't care what you say. C++ is both easier to use and less annoying than rust.
You are wrong.
how does it feel to be wrong?
@@sid4579 feels bad
have you spent an equal amount of time in both?
#teamcpp tho
Yeah, the tiny but loud Rust community have sniffed their own farts for far too long 😂
Smart pointers and RAII in your own classes get you all the memory safety. You never have to new and delete. std::visit and std::variant kind of do what Rust enums do, C unions can also be used but not as safe. C++ has tuples, but structs are always better. Smart pointers used correctly are actually no slower than raw pointers; people do use shared_ptr wrong though.
this. more people please recognize this. (also tuple destructuring & spreading is a thing as well).
One of the biggest wants for me is to have match/switch on enum/variant that compile time checks for coverage, something I am not aware of existing in C++ at present.
@@iverbrnstad791like -Wswitch and -Wswitch-enum?
Reference invalidation is quite possible without borrow checker, std::variant is terrible compared to Rust Enums, as you agree by saying they “kind of do” what the Rust one does… Rust has the real deal!
Agree with most, except "structs are always better." Use struct if you need struct. The power of std::tuple is that it's a generic type and can be used in generic code. In fact, some algorithms work on tuple-like types (tuple, pair, array). The key to genericity is concepts, which allows multiple types to be used in uniform ways.
okay, but here is a question, does rust has equivalent of std::launder from c++? No? So How do you wash your dirty pointers otherwise?!
It's such a horrible language that *most* (like 99%) of the software were written in this language long before that abracadabra rant in the video: game engines, games, operating systems, video and graphics software. I really don't get it. C and C++ give you freedom, you can do whatever you like. Introduction of additional abstraction into programming languages makes it extremely difficult to maintain all possible design questions. In my opinion C/C++ to this day are still the best programming languages and those who pass on studying them miss a lot in terms of programming skills.
Just because it can be and is written in C, doesn't mean C is the best choice. By this logic, if everything was writen in asembly that would be the best programming language, and I doubt I will find many ppl defending that position.
@@someonespotatohmm9513 Well, it's just my take. I really don't see how Rust or Go are more advanced to C/C++. They are hyped as the "next big thing", but in essence it's pretty much the same stuff with slightly different syntax. That's my point. Switching from Assembler to C and the C++ was really a game changing thing, you could feel boost in productivity. But switching from C/C++ to Go/Rust doesn't feel like that at all.
@@alexandersuvorov2002 Writing stuff in Rust only makes my head hurt because the syntax is so convoluted. If I was young enough to still be able to learn things maybe I might appreciate it, because it does some genuinely cool things, but I'm no longer capable of learning new things, so I'll stay with C++, because it's good, too.
@@insu_na I'm open to new ideas and new programming languages and I definitively don't want to be dinosaur advocating for FORTRAN and COBOL. I really feel sad when I hear people complaining about the new tech while I can clearly see what future is going to look like. For example, to me JavaScript was "wow moment", while Java Applets and Adobe Flash not so much. JavaScript clearly has bugs, but the entire concept of reusing SmallTalk ideas and closures was revolutionary by the time and many programming languages picked up on this concept. I'm exploring Go right now (mostly because of Ken Thompson participation) and it's clear that it's just slightly simplified version of C. And in this context the rants on C++ appear to me absolutely unjustified. It's quite old language, for sure, but we have to acknowledge the fact that we haven't created any language that is ready to make it a history.
Totally agree. Still, I think 90% of C++ features are just useless and plain dangerous to use. While it is true that no one is forcing me to use something I don't need, often at work this does not apply. There will always be that mf colleague that will pour nonsense C++ sugar syntax in the codebase to do what a memcpy would've done just fine. Freedom is beautiful, but too much is just plain chaos.
The part on tuple was enjoyable to me... I'm working with Python right now, and I'm so sick of tuples. So much values everywhere, and I don't have the slightest clue what half of them do !
I would also agree that out-parameters aren't a great pick. I rarely use those myself. Because I believe defining a struct for the return type and instantiating it with brace initializers is the best way to tackle this issue.
In Python, I just treat tuples like lists and everything works lmao.
C++17 added destructuring of tuples - so syntactically looks similar to returning multiple values in Go, so is a breeze to use and the code is clear
Whatever happened to return types? I've seen multiple void methods in C# that have a single out variable. It's stupid.
@@jesustyronechrist2330try editing tuples
In Julia they have something called NamedTuples, you can give names to elements in your tuples, and you won't forget what they are. No need to define a struct just for that :)
C++20 does finally have modules though sadly there's barely any libraries that support it meaning you'd have to wrap everything
And barely any compilers.
C++23 will provide the modules std and std.compat to solve that issue, let's hope that in the future new libraries created with modern C++ will use modules.
@@gagagero All three major compilers have module support. GCC is almost completely compliant with just two papers concerning some issues with the initial drafts of modules not being implemented. Clang is compliant to a usable state but also has a few edge case issues. MSVC is fully compliant.
But yes it would be nice if Clang and GCC also were fully compliant but that will probably still take a few months
Could you just use C language libraries that are used by python? Or are they deliberately written so that nobody but python can use them?
no point in using them, as C++ will have to export and speak the C ABI either way. so header files will still be arounf
I honestly like c++ but I haven't ever made a bigger project so I don't think my opinion matters much.
I literally have 3 repo's on my github and I'm proud of only one of them. (1 from when I was learning pure JS alongside HTML and CSS, and 2 made in C++)
Bjarne Stroustrup is brilliant. All that crap implemented on top of the existing C language with syntax and symantic backwards compatibility (mostly). And templates are still the most powerful generic, yet not always the easiest to use.
If you do bad things in C++ it compiles, it runs, it segfaults.
If you do bad things in Rust it doesn't compile.
You cannot make that skill issue argument equally, no.
A wrong program not compiling is better for bad programmers (and good ones alike) than it failing during runtime.
To sum it up: Rust is better.
While I do like Rust, there is an argument to be said for getting code to a working version faster. The thing is that C/C++ does let you get working code faster. So long as you do it right of course, you don't have to bother dealing with annotating lifetimes and all that. The danger of course is that if you do screw that stuff up then you're going to have a bunch of very annoying debugging problems.
It depends. There's nothing for Rust comparable in quality to C++ static code analysis tools. Rust gives you a better baseline safety for free, but for really high stakes safety it's not ready.
Call me crazy but I love c++. The main thing I like about c++ is that I can choose how much abstraction I want we where and in many cases I can use abstractions without sacrificing performance. I also like being able to do the dangerous low level stuff manually if I really want to. I do hate having separate header files and source files so I just write the implementation in the header file. Sure it's going to make compilation take a bit longer but soon I'll be able to easily convert those headers into modules once they are better supported.
@1:10 std::sum is a thing, as is std::accumulate. and std::transform_reduce. And std::reduce. And std::partial_sum. And std::inclusive_scan and std::exclusive_scan. I mean how many different ways to sum a collection do you need? Why does this guy complain about c++ without knowing what the STL can do for you? std::for_each isn't everything. Although that, too, can be used to sum a collection.
@1:27 what is first class support supposed to mean? std::tuple is a thing. The heck is he talking about? It even has variadic template arguments for a tuple of arbitrary length. And if you want something else, try std::vector if you want to be disgusting. Or make your own class. It's not hard. There is even structured binding to unpack them nicely.
```c++
float x{};
char y{};
int z{};
std::tuple tpl(x, y, z);
const auto [a, b, c] = tpl;
```
@2:00 oh smart pointers are slow? Have you measured that? std::unique_ptr is extremely simple and well optimized. It barely costs more than new and delete and for most systems the assembly instructions are even equivalent. There is literally no performance penalty for them. Since unique pointers are sufficient 90% of the time, they're just plain better to be using. As for shared pointers, yes they are slower. But who really cares about a few nanoseconds? Do you really need to optimize THAT part of your program? I'm sure there are better ways to spend your time. Go to godbolt right now and plug this in with -O1 or higher. It literally produces the same code.
```c++
#include
extern void f(int* p_i);
auto main() -> int
{
int* p_i = new int(31415);
f(p_i);
delete p_i;
std::unique_ptr up_i = std::make_unique(31415);
f(up_i.get());
return 0;
}
```
@3:00 C++ is a great language. It's low down and hands on if you want or need it that way, and as high level as you want with many great libraries. The problem lies with how people are taught c++. You don't need to know arrays, pointer arithmetic or bit shifting. Don't teach people cstrings in char arrays and printf. They don't need it, and it makes them worse programmers at worst and at best it discourages them and makes them think c++ is hard and they can't understand it. What they need to know is STL, data structures and the modern types like string and vector. Teach them how to write useful classes, not variadic functions. Teach them how to structure code with classes, structs, namespaces, enum classes, not how to write c programs that compile in a c++ compiler where you have to shove everything into functions in a global namespace and then have to come up with weird names. In short, stop teaching C, that's just baggage that you will never need to use. There almost never is a need for using new and delete. Raw pointers are fine as function arguments. Unique pointers get you 99% of the way where you need to go. shared pointers 0.9% and the rest you have to use weak pointers for. Almost any data manipulation, query or restructuring that you could ever need is covered by the STL. And when modules release with c++38 they will have fixed those horrible compile times, too. What tripped me up is the weird build system. But once I wrapped my head around compilation units and the fact that templated functions and class members aren't actually real functions and need to go into header files, I was good. C++ has a reputation for being difficult, but it really is just a matter of perspective. I know dot dot dot is where the fun begins, but I never had to deal with that. That library writer stuff, and I don't write libraries, and when I do they are simple enough to not require variadic templates.
@8:55 I agree. const should be the default, but it isn't. clangd does mark pretty much all the places where you can make things const though. It was a bad design decision made ages ago. but they can't just change it. I've learned to live with it. And constantly thinking about whether a thing should be const or not also helps in a way. That said, a lot of languages don't have const as default. python doesn't even have a const to begin with. or private members for that matter. c# has readonly and const, neither is default. javascript const is non default, but javascript sucks anyway. java doesn't have const as default. actually there are very few languages that I can name that have const as default. probably because it is annoying. you make a variable to mutate it. it's in the name. a constant is just a name for a value.
You can make `this` const by declaring the member function `const`. You think about that when you design your class. Does this function need to change any class members? No, declare it const. It's not about the this pointer, it's about the function.
@13:00 I agree. copying can be slow. Just consider all your constructors for all your classes and you'll be fine. A class that is correct with all of them = default is just the golden medal. If you don't want your class to be copyable, then that's fine. What's the problem? Alternatively make the copy constructors deprecated for a warning to the user if it is probably a bug, but not necessarily a bug and let them pragma out the warning and explain their actions if they need to copy.
@13:30 bad. don't use references to modify values. references should always be const. If you want to modify values, pass pointers, or use a return type. make tuple is hardly long winded, especially with template argument deduction. using references obscures the fact that you are changing the data. The best way would be to either name your function in a way that strongly suggests that you are changing a parameter, or return a data structure of some kind to hold the return values.
@15:00 and there is your problem. You are writing c code. what the hell are you doing needing to pass sizes and arrays around? the message should just be a vector or similar. let the vector handle the hard stuff like allocation. buff should contain it's own size and be dynamically allocated as required.
@15:30 use gsl::not_null
Sum types means something like std::variant, but good, with pattern matching. It has nothing to do with std::sum; it’s a term from set theory. First class means in the language rather than in the library. It’s my gripe about what I find annoying, and std::tuple and std::variant aren’t up to my standards.
That is an amazingly short list of C++ paper cuts. He could have gone on much, much longer.
Wish I had! I have more posts though!
Funny where I work we also have non nullable versions of smart pointers. They can not be initialized as null pointer, but they can be moved and after move the non nullable smart pointer is null, which renders them kind of useless and already caused a few crashes.
Yeah, that's exactly why you can't have moveable non-nullable smart pointers!
other programmers: this is an int
c++ programmers: i'll make this a typedef just in case i want to compile it for a 42 year old CPU
other programmers: this is a string
c++ programmers: thank god i don't need to typedef this because there already is a typedef of a typedef of a typedef of a typedef of a typedef just in case we need to run this cloud database driver on windows 1.0 or the apollo 11 hardware.
rewrite this message in 42 years, when your program has been written to run on a 42 years old CPU and sadly never got updated because one client keeps to say 42 years old CPU are the best and they pay for it
Yes. c++ has to run on a large number of platforms, including the one’s keeping your airplane in the sky.
yeah, they are 42 years old, sadly.
This is mainly a C problem, where when you need to print it out you don't know the specifier to use.
may I ask you, what's "int"?
@@ElementaryWatson-123 trick question, whatever you want it to be.
18:30 Yes, copy-and-swap is boilerplate and "MyClass& operator=(MyClass) = default" should be a thing. But it’s not tricky.
People get it so wrong though!
The non-nullable owning smart pointer can't be moved from because what would the value of the pointer be after you moved from it? The obvious answer would be "null", but, it's non-nullable. You're breaking an invariant if you do that. And one of the rules for move (a style rule, but this is a rule, not a guideline, your code is broken if you don't do this, even if your compiler doesn't tell you) is that the moved from object must still be in a valid state.
"You're breaking an invariant if you do that. "
Yes, but you could have it set so it throws on access so that the only valid operation for a nulled pointer is the destructor call. IMO the policy of making the moved-from state "valid but unspecified" is a mistake.
The more I use C++, the more I love C. I just don't want to worry anymore of some hidden behavior of my code: if I write C code, I am sure of what will happen and if a copy will be made. C++ hides stuff that I want in plain sight to see if needed. Headers don't bother me much, I just use them as interface to the outside world. Disclaimer: I work in robotics embedded systems.
but if it's your own code base you know where the hidden behavior is so why is that so bad? Not sure which hidden behavior you're referring to though...
@@HairyPixels Implicit calls to the default copy and move assignments and constructors, which you might forget even exist.
the simplicity of C is just awesome (as a self taught engineer)
@@jordixboy C++ isn't that complex either, but teachers and books tend to overcomplicate it by throwing an entire lexicon's worth of OOP theory at you.
@@HairyPixels I would say that if you are the main contributor and know 90% of the codebase, you would be fine with every programming language. However, in a company usually you are not alone. When working with many engineers, it is very hard to force a coding style upon everyone, and since C++ allows very different programming styles, this leads to a mess very quickly. Freedom of choice is a good thing, but too much freedom leads to chaos. Just my take on personal experience.
That's not how header files should be understood, they are required by the compile when objects are to be linked, ideally you wouldn't want to recompile every parts of the glibc at each compilation, header file only define the signatures, structures and symbols that have been implemented in the glibc. glibc is then linked by the linker when your program is compiled. Most people think of header files as libraries but it's not that, you can find single header libraries where the source code is in the header itself, this approach is fine for small libraries, however it quickly slows down compile time, why would you want to recompile the same module everytime you make a change? Header files are also the literal foundation of bindings, any language that want to allow other languages to bind has to be able to create an object file, and an equivalent to a header file somewhere so that the linker may still know what its dealing with....
13:47 this is wrong as well at C++11 and up if you mark the return type tuple your can literally just for example Tuple return { a, b }, this works for structs and classes as well.
C++11 you would need std::tie, but C++17 has destructuring.
Still not as good as just using ()s for the type and the pattern. Writing out std::tuple is too much. Remember this is papercuts, not serious issues😜
7:20
Do you really need multi-pass compilers for that? Just presume the identifier exist. Error some other time. I'm sure that's more complex but the ergonomics of not needing
redundant code for basic features of the language seems worth it. Consider the multiplied effort of every user of the language vs the implementation cost.
C++ compilers are actually multi pass.
But you need to still know what the identifier is declared as, not just that it exists. Maybe you need to implicitly cast an argument, maybe it has default arguments you need to put in, etc. So unless you go ahead and parse the source files for every compilation job separately, multi-pass is a reasonable method. Or implicit "header" files that get updated with the source file on demand.
Delphi or FreePascal are actually single pass compilers!
The development cycles are super fast... testdriven development ftw.
Tuples are bad if you're "using them wrong". What I love doing in Rust is just destructing the tuple once I'm using it. Then bundle it back up if I need to. And yeah, if I need a particular tuple a lot, then it'll be promoted into a struct.
Are you playing chess on Rust or something?
Tuples should only be used in (highly) generic code imho, otherwise just make a struct with named members, so much more readable. I barely ever use tuples/pairs, and I do write somewhat generic code from time to time.
Tuples are mainly useful for whenever you need a function to return multiple values that aren't specifically related in any way and are expected to be split up immediately on being returned.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
19:00 That C++ does not break/remove stuff is patently false. Examples I can name without looking up: auto_ptr (deprecated in C++11, removed in C++17), _constexpr_ implies _const_ for member functions in C++11 (thankfully immediately removed in C++14). For the standard library, there is a list on cppreference “Symbol Index (removed)”.
Holy crap, member functions can be constexpr? That would mean the object that calls them is also constexpr, then? And where would that object be declared? In what order would all that code be executed at compile time? It's mind-boggling.
@@ruanpingshan A member function being constexpr means it can be called in a constexpr (member) function. The object can be mutable. There's loads of documentation online. It doesn't mean that much, honestly.
"And the header files still have all the private members of the class inside...!"
IMnHO, THIS is the most horrific fail in C++, on par with simply having to wake up every day to program in either Perl or JS except as a matter of sheer survival.
And if you want to make a C++ wrapper of a C library, you still have to pollute your entire namespace with the C headers, because otherwise you can't declare private members using types from the C library. The only alternative is the ugly Pimpl pattern.
What's exactly your objections about private members in class? That sentence you wrote doesn't make sense.
@@ruanpingshan how is including headers suddenly becomes "polluting"? And of course, there are module in C++ as well.
@@ElementaryWatson-123 The moment you include gl.h, you have every single OpenGL function, typedef and macro in your global namespace. That's namespace pollution. And making C++ wrapper classes is not an easy solution, because if your gl_wrapper.h uses any OpenGL type, then you have to include gl.h in gl_wrapper.h, and whoever includes gl_wrapper.h will get everything from gl.h as well.
Smart pointer can be lightweight in the form of a unique_ptr and weak_ptr or heavy weight in form of shared_ptr. The problem is to properly handle unique_ptr (e.g. as part of a vector or other classes) you need to have more fundamental knowledge about move(), release(), swap() and copy() / the copy constructor.
Good lord, i love Rust now even more.
@@voidwalker7774 in Rust you also have your dyn, Box, Rc, Cell, Arc ... stuff you need to properly learn to use. The borrow checker might help though.
can't have a weak_ptr without a shared_ptr.
unique_ptr should usually be what's used for ownership and raw pointers for non-owned. unique_ptr is just as fast as raw ptr.
valid use cases for shared_ptr exist but they are the exception, not the rule. People just overuse shared_ptr.
@@KX36 Yep I have found one valid use of shared_ptr so far and I'm not even sure it was a good one (I used it to solve cache invalidation in a multithreaded context, that way things don't die immediately when evicted). Value types like vector are the thing I reach for first, unique_ptr second, and shared_ptr a very distant third.
@@voidwalker7774yes it's good for people that get headache when they try to use their brain.
15:19 - WTF is (const char *void mesg, ...)
Is it pointer to void or char. Choose one.
In C++ you cant use nullptr in (char *) function, obviosly.
Typo
I coded for agricultural, infrastructure and automotive industry. In this area C/C++ does an awesome job at tiny and custom ordered chips. But it's a completely different world of programming compared to anything related to web, cloud or desktop/laptop. Almost everything is fixed mapped in memory. You try to avoid stuff like an OS, garbage collection or networking at any cost as it only increases power consumption and system completely without providing any value to the user/customer.
I agree to an extend on safety features and possible bugs. But we have a lot of awesome testing tools, we need full or close to full testing anyway. If you write a vehicle or flight controller there better be no bugs in it, or you go to jail pretty quick.
In those kind of applications a "low feature" language is a great choice. But we do adapt Rust or Java for displays, and infotainment units. Anything thats more powerfull in compute and has no real command over the machine.
It's also not uncommon to invest the effort and optimizing stuff in assembly. Even tho i tapp out of the projects at that point. I only put physics i to C/C++ code and make sure the physical machine acts like i thought it would.
14:30 what the hell is a "const char *void mesg" parameter? I assume the void was a typo
That’s how you spot a c++ basher. Most can’t code their way out of a paper bag.
Yes and it’s fixed
Story from a senior. We used to learn PASCAL. A STRONG TYPED object oriented language. Those who are excited about RUST should first learn OBJECT PASCAL. This language is like 35 years old and does TYPE CHECKING, BOUNDS CHECKING etc, etc. What is this silly hype about RUST. ... The C language was chosen and preferred because PASCAL was totally inflexible. C became the standard and later C++.
One additional note. I learned C++ in 1994 ...
unique_ptr is generally, not slower. And so, while it's a smart pointer, it's not slower. There is a slight caveat. When you call a function that takes a unique_ptr, the caller still ends up having to check if the called function took ownership of the argument. But that is a very tiny speed hit, and only shows up in specialized circumstances.
Now, shared_ptr, OTOH, is slower than a regular pointer.
A unique pointer isn’t but a shared pointer is a tiny tiny bit slower because you need to increment a reference count but reading an int from memory adding one and writing it back is 10 cycles. And that’s with a change miss.
A clone in rust is a hell of a lot more when you copy more than one byte.
@@CallousCoder - That's not how unique_ptr works. unique_ptr is a very thin wrapper around an ordinary pointer. You are accurately describing how shared_ptr works though.
Isn't there an issue that you cannot store the pointer in a register since it has to have an address for the destructor to work?
@@IllidanS4 - No. That isn't an issue, except possibly in some very strange circumstances. If you are using the pointer by value (not a reference or a pointer to it) then the compiler has enough information to completely optimize the destructor.
But, it may be an issue if you are pointing to the pointer. But that'd be an issue with an ordinary pointer as well then.
@@Omnifarious0 Yeah I just fixed my text 😂 and I saw your reply. I thought they were talking about shared pointers because that’s the only one you need to count references.
>who abbreviates message like that (mesg)
Linux...
I thought it was gonna be a serious blog complaining about serious defects/flaws in c++ but it's just convenience issues. There is a cost to freedom and performance, and if you're too lazy and undisciplined to use it then don't. But don't complain about things that are due to your laziness.
As a C++ programmer this has made me interested in learning Rust... although the Rust foundation turned out to be weird. I guess there's a gap here for a better Rust.
Circle, Cppfront and carbon all looking good. Swift has good interop with c++ now so could actually become successor if not only apple controlled most of it
Exactly . Never tRrust the Foundation. The same people are still lingering there since the logotype debacle. What will they come up with next? something like Redhat, HashiCorp or Oracle ?
@@kevindelnoye9641 Swift is a very strange language though, with some baffling decisions. I have my gripes with Rust but nobody can deny that at least it's a solid core that solves what it set out to solve. Swift is filled with things that make you go "buh?" like the lack of const for classes and that awful syntax for callbacks.
Rust was made by learning from the mistakes of C++, Haskell, Java and others. If the Foundation is going to kill Rust, there will likely be a new language based on Rust's features. You can't waste time if you learn something new.
zig & cpp and I am good. rust can sugma balls
The real fail here is that this guy claims to be an advanced c++ teacher but doesn't know that the language already provides a "non-nullable unique pointer" option as a first class part of the language.
Yeah? What is it called?
@@steffahn I'll give you a hint...
&
What's "unique" about references? Are you assuming a different meaning of "unique pointer" than the typical one?
@@steffahn Granted, it not 100% parity of features, but its 99% of what people want with a unique pointer.
The whole reason why the smart pointers exist is to provide automatic cleanup and to give ownership semantics to the language.
If you take your arguments by reference and by value, you are signifying owership semantics.
Whoever created the initial variable, that they are now passing by reference, still own it. You cannot take ownership from them.
If you wish to pass ownership, you can pass by value and std::move to make your transfer of ownership explicit, even if its just symbolic.
Any cleanup will happen at the appropriate time.
I assume we don't need to discuss the non-nullness of references in c++
So what, in your opinion, is missing?
@@khatdubell I have only watched the video once, but from what I remember the author's point was that things aren't properly expressed in function signatures (nor documented, since people don't document shit).
I'll agree with your trade-off: Non-null pointers do exist in the form of references, and I think references in C++ are a great feature. But if you write a reference into your function signature, this signature isn't expressing that the function requires uniqueness - for example two parameters could be the same reference. Of course you can document such additional requirements, but then again, you can also document that a unique_ptr argument isn't supposed to be null.
1:42 I almost never access tuple fields, but use destructuring to bind the fields to variables.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
The C++ experience is like when your stomach grumbles for hours but when you finally get to the restaurant you realize you've entirely lost your appetite.
@@Robertoclos-ib7cc who are Allah's people?
Moved-from unnullable smart pointers can just be put into an undereferencable state (that is most likely internally null). They're still very useful.
And if you find yourself having to implement destructors or move operations in high-level classes, you're doing it wrong. Write low-level resource management wrappers, compose your class of those and let the compiler generate the special operations for you.
Ok ok. Another I hate C++ video. I love reading people's comments and opinions on a language that they probably never got past helloWorld...
...or that they noticed that for every new feature there are at least two new pitfalls. It's a language for lawyers and academics.
@@sprytnychomikfound one. Go ahead hate on a language that powers pretty much everything...
@@romangeneral23 What are you talking about? I don't hate C. I love it! : )
@@romangeneral23 You don't have a clue what you're talking about. 99% of the internet is powered by linux servers. How much C++ is there in linux again? Oh yeah, none.
@@sprytnychomik😹 that's classless from you
C++20 got modules which might appease those who don't like header files in 10-15 years if/when compilers ever support them.
Someone in some other comment said the major compilers already have support for them, with clang missing a few things, gcc a couple edge cases and msvc being complete. No idea how right that is, but maybe it won't take that long
@@user-sl6gn1ss8pcmake has basic module support (still experimental I believe), meson is still trying to figure out how to bake them properly, and dunno about bazel. I would guess modules will be ready to be used as of cpp26 release
I attempted to write my toy debugger in Rust a few years back. It was after that I realized that Rust is not amazing, at all. Lifetimes leak into every single thing - and everything becomes a chore of leaking the life times (to 'static) because you *know* the life time is ok, but the compiler doesn't think you know.
So you use unsafe. For a project like a debugger, that would involve wrapping the _entire_ code base in an unsafe block. That certainly is not great. Or amazing. Or developer friendly. On the contrary, for that domain, Rust makes you think about _all the things you DON'T want to think about, because you actually don't NEED to think about them_ - so that argument works for Rust as well. But now, you have a compiler that _thinks_ that it has resolved it to be true, that there are no aliasing going on - and boom. Foot-gun-fuck-land.
I vomit inside every time someone calls rust safe.
Its not safe, you just haven't done anything non-basic with it.
Even without using unsafe, i've managed to unleash monsters.
The only reason people think rust is safer than C++ is because those people don't compiler their C++ with warnings turned up and promoted to errors.
Lifetimes leaking into everything is usually a 'skill issue'. I had exactly the same issues when I started out, the solution is to use the right design patterns to store your data. Knowing when to use a handler or arena, knowing when it's okay to just do a deep-copy and eat the minor performance loss, and when to use Rc solves most of these issues. It's a real hurdle at first though if you're not used to it.
@@khatdubell >Even without using unsafe, i've managed to unleash monsters.
Could you explain? I'm super curious about safety issues in Rust. I know that at least one of them exist (since it's a Clang bug which the Rust team can't fix), so I'm wondering what you mean otherwise, or where you got undefined behavior issues.
@@Mond-mk7tkI've run into several issues, but its not like i've written them down.
The latest one, and this was like over a year ago now, was a threading issue.
Again, no unsafe code blocks, and the compiler "OK'D" everything, but i had a runtime error
That's about all the specifics i can remember at this point. Sorry.
@@Mond-mk7tk I don't think you understand the domain I'm talking about here. The data that the debugger manages is fine. But unless you want to do a *bunch* of copying of binary data, that has debug symbols encoded in a binary format - you must leak the life times. There's no way around this.
And that would be abhorrent, for a debugger to do. Especially when debugging a non-trivial application like Firefox, which has 2+ GB of debug symbol data.
In this case, Rust's idea of life times break down - and I've seen the libraries written to handle DWARF; they all use the leaking of life times, because otherwise, it would lead to more insanity and rigidity of the code.
Rust is not great for everything, it simply isn't. No language is.
Making Breadth First Search in C++ was easy, in Rust how ever it was a no go for me. I did not work out the life time things (since pointers are a must for this to not take up GigaChads of memory). I was curious about the speed of Rust compared to C++ using the same dataset for BFS. I also wrote and tested Go and Java versions, both very slow. Probably due to not using pointers.
What you mean by very slow? 2x, 5x, 10x slower?
How exactly your graph representation looks like? I remember playing with similar stuff and Java was about 2x slower only
How slow was your Golang version. I would like to see your Go
Almost anything involving graphs (especially undirected and with cycles) seems like a real pain to implement in Rust. I've even seen people in the community recommending unsafe Rust for graph data structures.
A std::variant is the modern c++ answer to the rust enum. I think the variant is much easier to work with safely than the union.
But terrible compared to Rust enum
How can one like pure c and scold cpp for something it inherited directly from c (like default non-constness) at the same time?
I mean I don’t like that fact about C either, but at least C isn’t pretending to have good abstractions while actually making things harder.
I can prefer C to C++ and dislike things about both of them. Preferring C doesn’t mean C is perfect…
@@jimmyhartzell4361 you can use only abstractions that work well for you. At least smart pointers, function templates and stl algorithms are ok, why discard them altogether?
C++s sum types (std::variant, std::optional) are practical, but they aren't real sum types, and it's very difficult to make them so. In Rust, is there an empty type? That is, one that cannot be constructed? The effect should be that for the empty type 𝘌, if we have 𝘱 of type 𝘌 + 𝘈, for any other type 𝘈, then 𝘱 is guaranteed to hold 𝘈? (Yes, I know many programmers would ask “what's the point of that?” It's a math thing, and it does turn out to be useful for reasoning. It's like having the number zero in the integers.)
Not exactly the same thing, but in Rust a function can return "!", which actually means it never returns a value. Think about an exit() function that aborts the program for example.
@@martiny.9366You can also just have an enum without any variants which makes it impossible to construct.
For sum types being practical they need pattern matching
@@MI08SKyou can do pattern matching on std::variant with std::visit.
@@MI08SK This is very true, and something that several people in the ISO C++ committee have been working on for years. It is considered a priority for the next standard release (C++26, I suppose). But I know, at least, Michael Park has been working on it since at least 2016, and had something working 2017, so ti's taken a (rediculously) long time.
I believe all objects should be copyable by default. Love this feature.
Do like the ints do.
6:55 You may like it or not, but it makes perfect sense. for larger projects, library components and APIs. Why on earth would you want to know the specifics of a function at compiler time? How about libraries and system calls that you don't program yourself? How about module/library interfaces where you only want to expose a minimal set of functionality and abstract its inner workings? Do you think a compiling a separate module should also have to deal with avoiding symbol and namespace collisions from every other module in your system? Do I NEED access to the full source code of the C++ standard libary's just to compile a program?
Isn't modularity and replaceability a major goal in software engineering?
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
unique_ptr literally generates exact same assembly as doing a raw pointer correctly. And shared_ptr generates the exact same assembly as doing a shared pointer correctly.
Except for When const is the default.
13:46 hard disagree with the take. "out" can be pretty useful if you relegate it to functions like TryParse and any other function which may conditionally fail to return a value but uses a boolean return to represent success so that you can easily throw it into an if with a local variable that is only scoped to it being valid. A great idiomatic way to avoid coding in exceptions imo.
Years ago I was about to proposed on cpp-moderated, how string-literals can be arguments of non-type templates. It was highly requested and would have enabled things like type-safe print (std::format) etc. in C++11. I've implemented prototype in gcc and clang (only gcc patch was public). It was really simple change - like 20 LOC, but 1000's in tests. Then I discovered that hell will brake lose due to mixed (wide/narrow) literals concatation. Never decided write this proposal for that reason. It would have been extension to C++11 variadic templates and author of those already agreed present it for commitee. Btw. similar defect was discovered with user-defined string-literals in about same time. It is really really hard to extend this language. But there is no way to push Rust to degree we sometimes have to do with C/C++. And when we do it, that code is messy and tricky for all other reasons than language. So, no. Rust or any other safety oriented language won't do the trick in most cases.
Already exists as of C++20 (P0732R2)
Wait, I get the hint that out parameters are bad? I use em all the time, what’s wrong with out parameters?
Is there any reason, except for legacy code base anybody would use modern c++, c with classes, in anno 2024?
No language is perfect. Choose the one you understand better.
duh C++ is literally 40 years old and built over on C yet someone who just existed yesterday moans about it cuz compared to modern times where everyone can write decent compilers if they want, lot of tooling & resources, variety of languages, a LOT of software engineers resulting in a bigger percentage of testing & creating much better software. Oh no C++ has this & that ? bruh the standard ain't breaking things to satisfy your ideal ideology of a language. The paths to make C++ better is by either improving it adding more features and teaching the modern C++ extensively to overcome the stupid misuse of the language or create a successor to it sth like kotlin or swift that's suitable for modern days unbelievable standards
How are smart pointers slow? Which type of smart pointer?
To all beginners. C++ learning curve is absolutely brutal.
It's not even linear, it's a fucking 2^n curve. Even I took C before C++, I still open the damn docs back and forth.
Despite having built-in "out" keyword in C#, it is considered a bad practice to use it.
and tuples are fairly ergonomic in c#
const is a C problem, C++ had to inherit.
Why is that a problem? The choice of default non-const is actually the right one. It's more often than not variables are non-const than const. If someone doesn't understand whether something should or should not be const, they aren't skilled programmers and usually compiler will stop them. There is no difference from the point of view of safety which default is used, people can be just as profligate with mutable as they are with const if they are not proficient.
"I don't know anyone other than game devs who say c++ is a great programming language" as a game dev, I can't understand why anyone would want to write anything but c, c++ or c# xD
hey man, I'm pretty good at python and built some games in it, but now I wanna try the real stuff and start building with unreal engine. I can dedicate 6 hours per day to learning, researching and building with C++. How long do you think I can become good enough to be hireable by a big studio?
7:25 In C++, private class members are part of the public interface.
There is even bigger problem with c++. It's the newish introduction of build tools that break everything in c++. Try build something with android and you notice that my 222kloc project cannot be modified any longer since every modification to a header file requires full compile taking 2 hours. Its build tools like gradle, cmake, ninja etc that cause the problem by insisting theorethically correct dependency graph, but when my modifications always modify both .hh file and .cc file together in single transaction, compiling 300 .cc files when compiling just one .cc file is enough for incremental compile is just completely crazy decision by the build tools. When taking plain makefiles into use and noticing that you can actually modify the code is such a nice feeling....
I might be wrong 11:44 I feel like he's just doing something fundamentally wrong he, he complaining the structure/class isn't abstracted to a movable reference for him that that has to be done explicitly in C++, sure it would be nice to have some syntactic sugar for this but his solution seemed to be convoluted.
And overriding the default methods unnecessarily, he should have been using a unique_ptr and moving that around to be fair the move still isn't implicit but you would have the std::move feature he wants without having to override default methods and have the other issue he had.
C++ is not going away anytime soon. In fact, no language is obsolete other than a very few considering how we define obsolescence in general. Rust? Zig? These languages will also have their niches. Computers in the distant future (within 30 years) will be radically different than what we anticipate. Analog computing units might make a comeback. AI is becoming mainstream. Governments are becoming interested in crypto. People like us who are either hobbyists or professionals might have to look elsewhere. I mean, parallel computing, HDL, VHDL, Assembly, etc. Then, there come field-specific languages like Mojo Python for AI, C++ for crypto, C++ for graphics, C for embedded systems and such. What language will be the de facto choice in quantum computing? People still do not have a clue. If fatty multinational corporations like Amazon and Google start leasing out quantum computers to common people, forget any leisure you'd have. 👍
Quantum computers are going to be very limited. This is largely because quantum algorithms themselves are ridiculously complex, so there just aren't many of them and they're not something an average coder is going to come up with on their own. Making quantum algorithms is basically a separate branch of math in itself.
No, digital computers are here to stay for your entire life time, simply because of one reason; relyability. Only digitial systems are reliable. This implies that C is also here forever to stay as the fundamental way of (relyable) computing won't change.
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
If I may share my thoughts, with all that high complexity of classes with the need to implement all those copy constructors and things and how easy it is to forget them, I now believe with C++ it is far more easy to make mistakes and accidentally introduce undefined behavior and crashes than it is with the simple C language, even though C does not have smart pointers or any RAII solution. C has always stayed a simple language, and that aspect wins out.
In that way I also believe that Rust is especially a replacement for C++ even more than for C, even though people mainly compare it to C and talk about that a lot.
Like it or hate it, C++ is still the de-facto standard language for doing so many high-speed real-time demanding applications.
Take the world of making plug-ins for DAW applications, for example. Things like softsynths, samplers, reverbs, delays etc are all done in C++.
Same with game-development.
And mostly the same thing for Operating Systems.
And embedded systems.
Yes there are other upcomers that are just as performant but they simply aren't the standards for doing these kind of things.
We may swear how much we want but it still ain't gonna change this fact!
For embedded systems and OS programming C is the standard, most widely used language, not C++.
@@Asdasxelc++ is still used, bjt that's true C (and asm) is the king of down to hardware code. c++ has to be stripped of some features to do so, but can still very well run
And I can’t complain about its annoying flaws?
2:52 Even gamedevs say that C++ sucks. We use it despite that.
Indeed. For game development, the only language I can replace C++ with, is Nim. And not currently, only after they implement cyclic imports (which will probably happen this year or early next year). I can't wait for that, so I did a little hack to achieve it.
As a hobbyist C++ programmer of 15~ years one thing that annoys me in C++ is the many different ways to define a type. I dislike also that a struct and a class are the same except that one is public and the other is private by default. I think I like Java's public and private denotions better.
There are a few things like that, which think just come down to backwards compatibility. Can use one and forget the other exists, or as a personal way to distinguish class and pod. I like to use structs only, with functional techniques while pretending cpp isn't object oriented.. Freedom language.😄
I don't think that languages like Java or C# are better in terms of encapsulation and information hiding. Actually I like the concept of splitting the interface/definitions in header files and the implementation in c or cpp files. Java and C# put all into one file. This is a hack beyond belief in my eyes. The only thing I regret in c++ is that you are forced to set the private section of a class in the header file as well. It doesnt make sence to me. Why have the client see this? It is not part of the interface. Oh yes, you can do tricks with the PIMPLE ideom, but this has its own drawbacks: You are forced to allocate your implementation object on the heap (at least I didn't find a way to implement PIMPLE without the heap).
I mean that's really not that bad in the grand scheme of things
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
All you have to do is read comments in HN on posts or comments that state or hint that C++ is imperfect:, and you'll see it. "C++ is fine, you're just not good enough for C++" (with the implicit "like I am").. Somewhere in my stack of long-unread books is a Sams intro to C++ with cover art that has a green lawn with "C++" cut into the ground, revealing hellfire and brimstone: a perfect metaphor for C++, the Borg of programming languages.
like to see mention of the way in which you can use c++ like rust with unique ptr and union types. I get that they are in rust with syntax but so many people talk like they are new ideas never seen before lol
Here is what he and you both seem to not realize. There is code written in C and C++ that was written 30 to 40 years ago that is still working and running today. You are talking every major OS system having to be rewritten if you got rid of C and C++ backwards compatibility. Most the network communication industrial controls for chemical plants, reactors, and so much more.
But it doesn't just come down to the actual work of rewriting all that code from scratch you have to retest all of it. It has to work on the hardware some of which is old as hell. I've seen Muxes, controllers and other systems decades old still in operation. That means for all that hardware you would need to write new compilers for each and everyone of them and ensure no bugs exist.
What a bunch of people who complain const isn't the default is going to do that without breaking everything. Yeah right.
Preach.............plus programmers were generally much better in the past.
I didn’t say throw out all existing C++ code. I just said there were some annoyances.
Honestly, all you really have to do to clear out the vast majority of C++'s actual footguns is use a static analyzer and Valgrind. Add in some good testing - which you should be doing anyway - and you're golden. It's not hard.
We have the tools.
You can go longer with a bad decision in Go than you can in Rust - is that a good thing though?
19:37, this next point is something I'm planning to solve with the PATH environment variable, let's say you built an app for the 1st version of the library I'm making but the library has since advanced to version N. Rather than make you update the app the user would instead be required to launch the app with the correct version of the library bound, for example:
> paw1 --start app ...
app ...
> paw2 --start app ...
error app not found
> paw --start app ...
error app not found
paw1 shall always map in version 1 of libpaw and the related directories, in this scenario the app can expect the entire ABI of libpaw to match that of the 1st version and any libraries that the app relies on besides libpaw to likewise rely on the same version of libpaw.
When paw2 is used instead the attempt fails because the app is not in the libpaw2 directories and thus not mapped in via the PATH environment variable. As for the final example, paw shall always map to the latest version of paw (in this case paw2) by default, there will be 0 need to maintain old APIs between versions (besides the possible scenario where there's no need to change them, buffer functions for example).
The 1st version of paw (paw1) will expect *.exe apps since wine can be used elsewhere to launch them, this simplifies the build process since you don't need to do multiple versions of the same binary (which would defeat the purpose of paw, to eliminate native programming as the default programming paradigm for C/C++/C#/Obj-C and instead make fully cross-platform programming the default.
For the ABI issue there will be separate directories for each ABI so there's not even a need to check against the back end of integer types like pawjd which by default maps to __INTMAX_TYPE__ (paw will insist on GNU compatible binaries so only GCC, Clang, etc are valid for compiling with). For intmax_t there's a whole bunch of crap apparently that goes on at the back to maintain ABI compatibility between x86 & x86_64 binaries etc.
For paw this is not even worth considering since the binaries simply don't get mapped in if they're not matching the current ABI so paw is free to break ABI compatibility as much as it likes between directories so long as the API remains the same for the version it's mapping to. Likewise because of those directories there's not a need to maintain API compatibility in the future if a compelling reason to drop/change it comes up (like security issues) so the compiler will be able to catch these differences and force an update of code where it matters.
@@Robertoclos-ib7cc wtf? God DOES exist, he is information itself, every bit of light, sound, etc that comes at us is just a representation of information that already existed before we were even born, before the universe even came to be. To deny God is to deny your own existence, it is to declare whole heatedly you are of the biggest fools there are on earth.
It is the same as declaring you can't look beyond your own bubble of senses to what lies beyond time and space. Until you do you will never find God in this lifetime and in the next it will be far too late for you to find salvation for your soul, to find pardon for your offences against God (like the one you just committed).
Lord knows I'm not worthy of him either but that doesn't change that he went to the cross in human form (Lord Jesus Christ) for ALL of us. He endured the price you will likewise endure if you do not refuse to acknowledge God as your Lord and trust HIS ways, not the ways of the blind like all who treat MAN MADE "gods" as as anything more than simple idols that need to be abandoned.
At best they're simple entertainment, at worst they're devils of satan deceiving the masses.
Want to return more than 1 type? Use structs. Everybody says tuples, but I have seen them being used only in the test code.
Besides that while agreeing that C++ is not beginner friendly, most of the things here are minor stuff in my opinion.
One question, where is he finding all those articles?
As an ex basic(s) ex pascal ex Oberon ex java ex js ex ts ex Erlang ex lua ex c ex fortran ex Haskell ex prolog ex clisp ex python c++ dev, h files are not that bad if you keep just your pure set of interfaces in it. U r holding it wrong. Repeat after me: only std lib, templates and pure virtual interfaces in headers! Also, just have factory classes/static functions in the interfaces that only return sh ptrs of the said pure virtual interfaces! All of this goes away!
Wait, can I do that in C? I got to give it a shot. What do the C files look like though? I guess you treat it all like mini modules with mini interfaces
In the name of Allah, I invite you to worship Allah alone: I bear witness that there is no god but Allah, and I bear witness that Muhammad is the Messenger of Allah. These words make you a servant of Allah. ............ .........
19:14 No, even mem::uninitialized wasn't removed, only depreciated.
Just-tool-people are not experienced. Might be old but hardly experienced.
It always comes down to Turing completeness for them.
The downside of C++ :
requires skill through malding
Languages are imperfect, but you can learn a subset of them and patterns in them that are reliable, then focus more on the interesting stuff, that is, what you're coding and not necessarily how you're coding.
1:30 What about std::variant? It’s C++17, sure, but saying C++ doesn’t have sum types is a lie.
Ersatz library fakery isn’t anywhere near as good as the real thing
9:00. Where I work, const has been in the linter so long, that it's ingrained in us to use cost by default.
Except it's JS, so it's not a const const. We haven't switched to DreamBerd yet, ik ik.
The AGI for the mech "Smith" in the Jennifer Lopez Netflix movie _ATLAS_ is coded in C++
The problem with adding rust like enums to c++ would be that c++ would need to have pattern matching witch will probably come in c++ 26
Pattern matching isn't a thing in c++23 and probably won't be in c++26 either or any future standard
What's the difference in enums from C++ and rust? Is it just types?
@@HelloThere-xs8ss c++ enums are similar to rusts but they can't hold a value
@@MI08SK oh that's right
what's wrong with std::visit and overloaded?
Is C++ that bad? I'm trying to learn C++ to develop games and use Unreal Engine.
don't listen to this people : D if c++ was bad they wouldn't use LLVM to create rust crap language . all rust is based llvm and gcc and those are written in c/c++ XD this people are out of their minds . rust compiles the same code c++ does cause its all written in c++ it just rust doesn't lets you to have freedom to shoot at your foot XD .
@@Phantom-lr6cs No. The reason Rust uses LLVM to optimise it's output is because of the work required to replace it. They're using the "if it ain't broke, don't fix it" methodology.
Just because a tool written in a language works doesn't mean the language is good.
C and C++ are old and crufty. C is still fine because it's super simple. The problem is these languages are awkward to use because they don't have the modern niceties. They often got the defaults wrong.
There are languages to replace these:
Rust is a C++ 2.0
Carbon is a C++ 2.0
Zig is a C 2
Odin is a C 2
@@Hector-bj3lsNothing is replacing C/C++ because koolaid drinkers want modern niceties roflmao.