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

Поділитися
Вставка
  • Опубліковано 23 січ 2024
  • 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
    @wolpumba4099 5 місяців тому +13

    *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
    @amaama4140 5 місяців тому +1

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

  • @MalcolmParsons
    @MalcolmParsons 5 місяців тому +2

    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.

  • @sunnyyasser5625
    @sunnyyasser5625 5 місяців тому +3

    Great talk!

  • @SimonToth83
    @SimonToth83 5 місяців тому +2

    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).