C++ Common Knowledge - Dawid Zalewski - Meeting C++ 2023

Ғылым және технология

C++ Common Knowledge - Dawid Zalewski - Meeting C++ 2023
Let's face it, you can get by just fine in C++ without knowing what std::launder does or how to use parameter packs with std::index_sequence. However, if you consider yourself a well-rounded C++ programmer, you can't escape being familiar with the one-definition rule or understanding the deterministic object destruction guarantees. That's just C++ common knowledge. Yet, such foundational items are often overlooked and their details are glossed over. Unfortunately so. Let us take a step back and talk about the basics, digging deep into the core language. Let's start making the catalogue of the C++ common knowledge. Besides the topics already mentioned, we'll talk about the lookup rules, friends, initialization, member functions and others!

Пікірлер: 6

  • @wolpumba4099
    @wolpumba40994 ай бұрын

    *Summary* *introduction* - 00:00 Dawid Zalewsky introduces the topic of common knowledge in C++. - 00:26 Dawid mentions he enjoys reading old programming books to learn about C++'s history and nuances. - 01:21 The talk aims to cover important common knowledge items in C++, some of which may be overlooked or unknown, especially to those new to the language or certain aspects of it. *motivation for the talk* - 01:44 The talk will modernize common knowledge items and will not cover everything from the book with the same title. *buggy program example* - 02:02 A short, buggy C++ program is introduced. - 02:20 The program includes a base class with data members and a conversion operator. - 02:34 A named object class is also shown, which includes a comparator operator. - 03:01 The named object class is used in conjunction with a named heap class. - 03:29 The named heap class inherits from the named collection base and includes data members for tracking the smallest and largest values. - 03:49 The named heap class also follows the rule of five, with proper constructors and destructors. - 04:07 The classes are used together, with a function that requires a collection passed by unique pointer hinting at polymorphism. *compilation and runtime issues* - 04:57 The buggy program compiles with modern C++ standards but has runtime issues. - 05:09 Only a few compiler warnings are triggered, which may be missed. - 05:22 The program crashes or runs indefinitely despite compiling successfully. - 05:35 The program violates more than 10 important best practices in C++. *list of issues in the program* - 05:41 Dawid lists the issues in the program: uninitialized data members, undefined behavior, implicit conversions, assignment vs. initialization confusion, one definition rule violations, exception safety neglect, memory leaks, const correctness issues, infinite recursion, and object slicing. *approach to fixing the program* - 06:45 Dawid proposes to fix the program by walking through 12 different items. - 07:28 Uninitialized variables are indeterminate and can lead to undefined behavior. - 08:05 Removing the user-provided constructor that does nothing helps avoid uninitialized data members. - 09:14 The order of declaration in a class determines the order of member initialization. - 11:20 Data members should be initialized in the correct order to avoid indeterminate values. - 11:41 Assignment should not be confused with initialization, and using curly braces can help clarify initialization in constructors. - 14:08 Implicit conversions should be avoided as they can lead to unexpected behaviors. *issue with implicit conversions and constructors* - 14:25 The named heap class has a converting constructor from a string, which can lead to implicit conversions that may be unintended or nonsensical. - 14:58 Implicit conversions can cause issues, such as allowing nonsensical function calls to compile without error. - 15:43 To prevent these problems, Dawid suggests making the constructor `explicit` to disable implicit conversions. *problem with implicit conversions and comparison* - 16:03 Implicit conversions in comparison operators can lead to unexpected behavior when comparing objects of a base class. - 16:24 The named collection base has an implicit conversion operator to a named object, which has a defined equality operator. - 17:04 Marking the conversion operator as `explicit` can prevent unintended comparisons. *one definition rule and its implications* - 17:17 The one definition rule requires each object to be defined only once across all translation units. - 17:51 A constant defined in a header file can lead to multiple definition errors if included in multiple source files. - 19:01 The linker will complain about multiple definitions of the same object if included in different translation units. - 20:20 To resolve this, you can mark the variable as `inline` or make it `static` or `constexpr`. *importance of object construction and RAII* - 21:15 Only fully constructed objects benefit from RAII (Resource Acquisition Is Initialization). - 21:34 There is a potential problem with resource allocation in constructors that may throw exceptions. - 22:13 If an exception is thrown during construction, the destructor won't be called for the partially constructed object, potentially causing a resource leak. - 24:35 A solution involves delegating to a default constructor that initializes resources to null, allowing the destructor to clean up properly. - 25:42 A better approach is to follow the principle of one class, one resource, to simplify resource management and ensure RAII. - 26:49 With modern C++, you can use `std::unique_ptr` or `std::vector` for automatic memory management. *extra `this` argument in member functions* - 27:15 Member functions have an implicit `this` pointer as an extra argument. - 27:27 Understanding the `this` pointer is important for grasping how more advanced features like `deducing this` work. - 28:04 The named object overloads the inequality comparison operator, which takes an additional implicit `this` parameter. - 28:35 The presence of the `this` pointer in member functions is crucial for understanding object behavior and method calls in C++. *function call chain issue with implicit `this`* - 29:14 There is a canonical implementation involving a member function and a free function that piggybacks on the member function. - 29:32 After inlining, comparing two named objects using the equality operator can lead to a call chain that causes infinite recursion due to rewriting rules in C++20. *infinite recursion issue and its resolution* - 30:28 The infinite recursion occurs due to the compiler rewriting the comparison to call itself repeatedly when the member function does not match the required const qualification. - 33:25 To fix this, the member function should be made const to match the const qualification of the arguments. - 34:11 Making the member function const allows the correct chain of calls to proceed without infinite recursion. *discussion on hidden friends and defaulting functions* - 34:57 The compiler can synthesize certain comparison operators, so it is unnecessary to define both. - 35:16 Hidden friends are used to hide functions from lookup unless the arguments explicitly match the parameters of the function. - 37:03 To prevent unwanted implicit conversions in comparisons, the comparison operator can be moved inside the class and declared as a friend. - 38:43 With C++20, it's possible to default the comparison operator and declare it as a friend, which simplifies the code and ensures the compiler synthesizes the other comparison operators. *necessity of virtual destructors in polymorphic classes* - 39:15 Polymorphic classes need virtual destructors to avoid memory leaks. - 41:07 The named heap and named collection base classes lack virtual destructors, which can cause memory leaks when objects are destroyed through a base class pointer. - 42:09 The fix is to add a virtual destructor to the base class, allowing proper destruction of derived class objects. *issue of object slicing* - 42:49 Object slicing occurs when a derived class object is copied through a base class reference, losing part of the derived class's data. - 43:19 An example of object slicing is shown where a named heap object is copied, but only the base class portion is copied, not the derived class data. *continuation of object slicing issue* - 44:19 Function taking named collection base by copy results in object slicing, copying only part of the object. - 44:50 Object slicing can lead to unexpected behavior and crashes when casting or using the sliced object. - 45:09 A potential fix for object slicing is to ensure the correct class is used when making a copy or passing objects to functions. *conclusion of the talk and recap of knowledge items* - 45:43 The talk concludes with a recap of the 12 common knowledge items discussed. - 45:51 All the mistakes discussed were demonstrated within the first few slides of the presentation. - 46:06 The audience is encouraged to try out the examples themselves to understand the issues better. *Q&A session* - 46:25 A question from the online audience about when to define the `==` operator if the spaceship operator is asked for. - 47:00 The answer is that with the spaceship operator, defining the `==` operator is typically unnecessary. - 48:34 A concern about implicit conversions that the compiler can make, specifically converting comparison operators, is raised. - 48:48 The rule introduced in C++20 allows the compiler to rewrite comparisons when one is lacking. - 50:01 A question about best practices for adding `inline` to `constexpr` variables is discussed. - 50:56 The answer clarifies that `inline` allows multiple definitions and the Linker ensures there is only one object created. - 51:38 A comment is made that if the spaceship operator is explicitly defined and not defaulted, the `==` operator must also be explicitly defaulted. - 52:23 Clarification that the `==` operator is not always provided automatically even if the spaceship operator is present. - 52:35 A question about handling bad memory allocations (`bad_alloc`) is asked. - 52:58 The response suggests that running out of memory is usually a terminal situation for a program, with limited options available. - 53:54 A historical anecdote about memory allocation strategies is shared, including reserving a small amount of memory for emergency use. *closing of the session* - 54:15 The speaker thanks the audience for attending the talk and participating in the Q&A. Disclaimer: I used gpt4-1106 to summarize the video transcript. This method may make mistakes in recognizing words.

  • @amaama4140
    @amaama41404 ай бұрын

    Mr. Zalewski always surprises me with his deep technical talks. Really enjoyed it.

  • @sunnyyasser5625
    @sunnyyasser56254 ай бұрын

    Great talk!

  • @MalcolmParsons
    @MalcolmParsons3 ай бұрын

    Defining operator == is still useful when also defining operator because operator == (and operator !=) can return early when 2 containers don't have the same size.

  • @SimonToth83
    @SimonToth834 ай бұрын

    The explanation for hidden friends was a bit confused. The information that got lost (I had to rewind to double-check) is that named_collection_base and named_object are unrelated types, named_collection_base simply has an implicit conversion to named_object. Hidden friends are still visible in many situations (following ADL rules).

Келесі