C++ Weekly - Ep 322 - Top 4 Places To Never Use `const`

Поделиться
HTML-код
  • Опубликовано: 4 сен 2024

Комментарии • 82

  • @aDifferentJT
    @aDifferentJT 2 года назад +22

    #2 and #3 are basically the same thing, don’t const values that are going to be returned. This is basically a subset of the rule not to const things that are going to be moved.

  • @sirhenrystalwart8303
    @sirhenrystalwart8303 2 года назад +11

    Thank you for #1! I get into arguments all the time with people at work when they want me to const member variables. Now I have a solid resource to point them to from a respected authority.

  • @kethernet
    @kethernet 2 года назад +39

    I'd say 5) Don't take by const reference if you need to keep the value. I see a lot of reflexive `const std::string&` arguments where the string is then copied inside the function. `std::string` in that case is better, since it can be moved into the function, then moved where it needs to go. Perfect forwarding, or adding an overload of `std::string&&` work too.
    Also, with C++17, there's really no reason for `const std::string&`. Just take `std::string_view`.

    • @baardi2
      @baardi2 2 года назад +9

      There's a few reasons I can think of, e.g. when passing it in to an api taking null-terminated strings.

    • @ChiliTomatoNoodle
      @ChiliTomatoNoodle 2 года назад +4

      @@baardi2 Yup, std::string_view with null-terminated strings is a pretty annoying combination.

    • @ajinkyakamat7053
      @ajinkyakamat7053 2 года назад +3

      Another reason you might not want to do "std::string const &" is exceptions. Though rare, if the copy fails and raises an exception your function is not exception safe. But taking a copy means that the exception happens outside your function and u just move it to where you want inside the function.

    • @friedkeenan
      @friedkeenan 2 года назад

      @@baardi2 I hope in the future a sort of "zstring" (the term for a view of a string that's null-terminated) can become part of the STL

    • @_RMSG_
      @_RMSG_ 2 года назад

      @@ChiliTomatoNoodle What about adding the null terminator when passing to those APIs? does that defeat the efficiency afforded by string_view?

  • @ekondis
    @ekondis 2 года назад +11

    #1 sounds disappointing. I find of value to set a member variable to be const when you are intending not to modify it. This is a negative side effect.

  • @alagner88
    @alagner88 2 года назад +8

    Note that returning const value (4) had been advised (e.g. by Scott Meyers) before C++11 and its overloading on value category was introduced in order to prevent assignment to rvalues. Granted, it is hard to defend nowadays but imho still worth to keep it in mind especially when dealing with legacy code.

  • @DmitryReshitko
    @DmitryReshitko Год назад +4

    Just came across with this video. Very helpful, but #1 looks like a "premature optimization". Using const for your members is not a typo, but part of the expressiveness and semantics of your code. So it is worth to mentioning that this is a tradeoff, and if your class can be moved and you are concerned about performance, then removing const will help.

    • @TrueWodzu
      @TrueWodzu 11 месяцев назад

      Exactly, it is a bummer that you lose some performance just because you want to have your member const, but it is a cost I am willing to take, to make my code cleaner.

    • @fullaccess2645
      @fullaccess2645 10 месяцев назад

      @@TrueWodzu why not make a CONST macro and define it only on debug build? Wouldnt that be ideal?

  • @Qazqi
    @Qazqi 2 года назад +1

    I was close. I thought for sure that #2 was going to be "don't top-level const parameters in a forward declaration", but it was more an extension of #3, and my version of #3 was "don't const things that you intend to be moved from".

  • @joeblinx4379
    @joeblinx4379 2 года назад +3

    Hi!
    In your #1 point "Do not const member variables", I'm surprised that you didn't talk about "reference member variables" since a reference is a "non assignable" variable, it can be consider as a "const member variable" with some other drawback like the implicit deletion for copy and move assignment and not just the move one.

    • @viniciusferrao
      @viniciusferrao 2 года назад

      I was expecting some info regarding this, although I think this is out of context on the video. But a note is definitely appreciated.

    • @cppweekly
      @cppweekly  2 года назад

      Yes, you're both correct, and I also avoid reference member variables, but not the point of this video.

  • @TrueWodzu
    @TrueWodzu 11 месяцев назад

    If I would follow every single rule that Jason defined over the years I would never finish a decent C++ program. It is good to know that such things exist but on the other hand you have customers and deadlines to meet.

  • @fcolecumberri
    @fcolecumberri 2 года назад +5

    about #2, how many times do you create a function that receives an object that wont be changed and you just returns it? (non-rhetorical serious question)
    I mean, if you change it, it can't be const rendering this point useless
    but if you don't change it why do you returns it? outside the function the user of the function already has the object.

    • @User-cv4ee
      @User-cv4ee 2 года назад +1

      Convinience? Especially if the object has complex initialization and we don't want code duplication.

    • @cppweekly
      @cppweekly  2 года назад +4

      You might have a conditional that says "return some new thing or returned the thing that was passed into me", but I agree this would be very rare. It's just a thing to be aware of.

    • @fcolecumberri
      @fcolecumberri 2 года назад

      @@cppweekly that's a great answer.

  • @dennisrkb
    @dennisrkb Год назад +1

    Never make your member variables const, they prevent moving. If you don't want anybody to change your members, make them private and only offer const public member functions.

    • @cppweekly
      @cppweekly  Год назад

      Yup, that's in the video.

  • @yash1152
    @yash1152 Год назад +1

    7:27 whats clang-tidy?

  • @TryboBike
    @TryboBike Год назад

    Regarding rule #1.
    What about classes/structures which explicitly define move assignment and constructor?

    • @cppweekly
      @cppweekly  Год назад

      It would be hard to do anything meaningful and correct in them, and the complication is probably not worth the effort.
      But it's theoretically possible there's a use case there.

    • @TryboBike
      @TryboBike Год назад

      @@cppweekly
      I ask because rule #1 throws some sand at what I do at work. In essence - the use case is that I pass around lots and lots of structs. Which were classes before I dug into it. Basically - what I pass and/or return are structs which have all the data members public _and_ const for ease of access. Each struct defines copy/move operator and a matching constructor. If you want a new one, you are supposed to construct one either from scratch or by destroying an older one.
      The operators themselves are defined as an explicit call a destructor followed by placement 'new' and a move/copy constructor respectively. It _seems_ that MS compiler does make moves of std::strings in this case but debugging standard library is ... challenging.
      Now - I admit, I may have overthought this. But I like my m_foo.m_bar.m_member instead of m_foo->GetBar()->GetMember(). From profiling this code I get nice speedups as well.

  • @raakakadaaka
    @raakakadaaka Год назад +1

    This may seem a bit of a silly (and unrelated) question and I've tried looking out for answers and haven't gotten any. Is it possible to run Compiler Explorer on my code locally? I know I can generate the assembly instructions and all but it's not the same as having it side by side moving with your code. Or is it? That's what I wanna know, Thanks!

    • @cppweekly
      @cppweekly  Год назад +2

      You certainly can, set up a local instance and include your own directories. It's a bit tricky sometimes, but should work out.

    • @raakakadaaka
      @raakakadaaka Год назад

      @@cppweekly thanks Jason, I’ll give that a shot.

  • @forgetfulfunctor1
    @forgetfulfunctor1 2 года назад

    the first example sounded almost like "use copy elision", except...
    is he saying that if we don't use copy constructor, and we do have a const return type, then the compiler uses copy ASSIGNMENT rather than move assignment?

  • @calebtaylor8472
    @calebtaylor8472 Год назад +1

    Is it worth avoiding const data members of a class if it isn't copyable at all?

    • @cppweekly
      @cppweekly  Год назад +2

      if you have explicit disabled copy and move, then it's irrelevant

  • @DamianReloaded
    @DamianReloaded 2 года назад

    Great insight. 10/10

  • @videojeroki
    @videojeroki 2 года назад +8

    When you pick C++ for performance reasons and you find out that a single trivial const "error" make your effort irrelevant...

    • @ChaotikmindSrc
      @ChaotikmindSrc 2 года назад +7

      I wouldn't go that far, it is certainly better to be aware of that, but you can still get very good perf comparing to other languages

    • @videojeroki
      @videojeroki 2 года назад +4

      @@ChaotikmindSrc yes i exagerate a bit but you get my point ;)
      I love c++, not because it is great, just because i grew up with it. if i would start from scratch today, not sure i would pick it ^^

    • @ChaotikmindSrc
      @ChaotikmindSrc 2 года назад

      @@videojeroki Oh well i can relate to that
      i would hope for an utopic world where some of the c++ horrors just go aways XD
      The language really feels over-engineered at the moment.

    • @videojeroki
      @videojeroki 2 года назад

      @@ChaotikmindSrc Usually i try to code as clean as possible to make the optimization as simple as possible (preferably someone else) .
      sometime simple code looks like over engineered indeed. So hopefully this code is pushed and never seen again :D

    • @ChaotikmindSrc
      @ChaotikmindSrc 2 года назад +1

      @@videojeroki I come from a darker place where i was reading assembly before taking a coffee and programming until the sun appears while drinking whisky.
      Took a long time for me to write "clean code" YMMV
      I'm partly healed tho ;)

  • @kimhyunpil
    @kimhyunpil 2 года назад

    Thanks video

  • @Pi03k
    @Pi03k 2 года назад +2

    const first

  • @milasudril
    @milasudril 2 года назад +1

    Strictly speaking, moving from an object may break an invariant:
    template
    struct WithAtLeastOne{
    explicit WithAtLeastOne(typename Container::value_type&& obj) {
    data.push_back(std::move(obj));
    }
    private:
    Container data;
    };
    ??

    • @alagner88
      @alagner88 2 года назад

      Isn't that the moment when rule of 5 should be used instead of relying on default implementations?

    • @SonicFan535
      @SonicFan535 2 года назад

      In this case, you could implement your move operations in terms of swap() to avoid breaking the invariant. Doing so would still conform to the standard recommended practice of leaving your moved-from object in a "valid, but unspecified" state.

  • @matinjalali4409
    @matinjalali4409 2 года назад

    U r the best👌

  • @negidrums915
    @negidrums915 2 года назад +1

    Is there any case we must use const to avoid performance issue (not human error)?

    • @deanjohnson8233
      @deanjohnson8233 2 года назад +2

      Only in very rare circumstances. Almost always, the compiler will make its own determination about what is const and what is not by analyzing the code and will optimize based on that regardless of whether you explicitly use const. One case I can think of where const may have a performance benefit is with global values used across translation units. In this situation, the compiler isn’t going to be able to analyze all usages of the variable and so it has to assume that it is non const. If you explicitly mark it as const, the compiler can trust you and use that for some additional optimizations.

    • @cppweekly
      @cppweekly  2 года назад +3

      Even without multiple translation units, if you mark a static (implicit or explicit) variable const, the compiler can move it to "static initialization" which means you can see a whole range of possible optimizations.
      I demonstrated this in my CppCon talk ruclips.net/video/zBkNBP00wJE/видео.html

  • @vladimir0rus
    @vladimir0rus 7 месяцев назад

    Is it possible to detect all such cases automatically?

    • @cppweekly
      @cppweekly  6 месяцев назад +1

      not with any tools that I know of.

  • @dagoberttrump9290
    @dagoberttrump9290 2 года назад

    can't you move construct const values? Granted that you write your own move constructor, I would say it's not too bad to have const members no?

    • @cppweekly
      @cppweekly  2 года назад

      you can `const auto value = std::move(othervalue)`
      but you cannot `const auto value = std::move(someconstvalue)` in any way that makes logical sense.

  • @originalmiu
    @originalmiu 2 года назад +1

    Note: If you remove the puts() calls from struct S constructors and destructors, the compiler can optimize-away many of the bad uses of const. The puts() calls themselves are causing I/O, which forces the compiler to follow the C++ language rules for which ctors/dtors are logically called, to determine the correct output of the program. In other words, the puts() calls you're using for debugging this are causing the extra work, and not the bad const's.

    • @cppweekly
      @cppweekly  2 года назад +2

      You are over thinking this.
      The real point you are trying to make is that none of this matters if the types are trivial, which is a fact. I even did an entire conference talk about this specific topic:
      ruclips.net/video/ZxWjii99yao/видео.html

  • @yash1152
    @yash1152 Год назад

    0:51 any reason why you are using struct objects rather than class objects?

    • @cppweekly
      @cppweekly  Год назад

      It makes the code shorter for my purposes.
      But it's important to know that there is no real difference between the two in C++. It's mostly a style a choice.

    • @yash1152
      @yash1152 Год назад

      @@cppweekly not totally related, but not totally unrelated either:
      * have u attended/watched the talk about cpp2 titled "Can C++ be 10x Simpler & Safer? - Herb Sutter - CppCon 2022"
      * to me, it seems its syntax is so similar to Kotlin
      * but anyways, what are your thoughts on that approach/direction?

  • @Dizintegrator
    @Dizintegrator 2 года назад

    If I dont const ANY member data, this would ultimately result into not using const member functions... So "Almost never use const" then? ;)

    • @cppweekly
      @cppweekly  2 года назад +1

      100% the wrong take away here. Const member functions have literally nothing to do with const member data *at all*
      you need to watch my last video on const member functions ruclips.net/video/bqd9ILyQRxQ/видео.html

  • @xaxi5
    @xaxi5 2 года назад

    All effects are fully expected. This video just demonstrates the selected compiller works by standard. It's more interest to see is there some compillers or options to break expectations?

  • @hanyanglee9018
    @hanyanglee9018 2 года назад

    OK cool, thanks. Probably this is also one of the major difference from c++ with almost all the other languages. I remember in at least js and python, people are recommended to use const as possible, but const seems not to help in cpp. They are too different.
    Probably anything like 4 to 20 bytes can be const without any significant trouble because their ctor or copy are almost the same size, but if the object is bigger, then I guess the const keyword messes.

    • @cppweekly
      @cppweekly  2 года назад +3

      As I started the video with, you should use const almost everywhere. These are the exact 4 times to NOT use const. They help with readability, correctness, and in some places performance.

    • @hanyanglee9018
      @hanyanglee9018 2 года назад

      @@cppweekly OK. Thanks. I've been away from c++ for years. I saw people battle with the grammars with these tricks only to get the compiler to do specific jobs. If people can script for the compiler and specify the concrete behavior for the compiler, most the tricks against the compiler would be gone. I remember in another video, you mentioned the constexpr causes a lot trouble. If it had another layer, it would be like:
      {"compiler instructions";
      compile_time_const.push_back("some_variable")
      }
      int main(){
      const int some_variable = make_value(...);
      }
      I tried to tell people of this idea but no one cares.

  • @anon_y_mousse
    @anon_y_mousse 2 года назад

    Looks like YT deleted my comment, but the gist of it was, I love your videos because they help me learn more about C++ and keep my skills with it up to date. However, they also give me more ammunition in my crusade against C++ because it is still a language I vehemently dislike. I wish more people would just use C and for fancy syntactic sugar, create a language that's better than C++, so not Rust.

    • @yash1152
      @yash1152 Год назад

      have u watched the video about cpp2 presented in cpp-con2022 which talked about backword compatibility only on demand. It was solid.

  • @atillakayrak4293
    @atillakayrak4293 2 года назад

    It's crazy that a 2022 compiler is not smart enough to know that a local const value which will be be out of scope on return should be moved

    • @cppweekly
      @cppweekly  2 года назад +3

      you cannot MOVE a CONST because it is a Constant!
      At best it could be elided, but never ever moved. ruclips.net/video/ZKaoR3dP9uM/видео.html

  • @_RMSG_
    @_RMSG_ 2 года назад

    I can't wait to use const in all of these places

  • @stevewilson5546
    @stevewilson5546 2 года назад

    C programmers are sadistic masochists. I didn't realize there were so many ways you could break the code. I'll stick with Turbo Pascal for short programs and Delphi for larger programs (minus Object programming, of course.)

  • @chololennon
    @chololennon 2 года назад +3

    This language is really really awful (and before anyone says something about it, I have been programming professionally in C++ for more than 30 years). I can't believe that for every sentence I write I have to check what the compiler emits at low level 😱

    • @deanjohnson8233
      @deanjohnson8233 2 года назад +10

      Nothing forces you to check this. Other compiled languages are going to have similar issues where a small change can drastically change the compiled representation. I see plenty of videos just like this for c# that explore how tiny changes can have huge impacts on the generated code. IMO, this is the reality of compiled languages - they tend to be so much higher level than what they compile into that you are going to have these kinds of situations.
      I think we talk about these issues in c++ more because c++ programmers tend to love to squabble about low level optimizations like this.
      I haven’t reached your level of experience yet, but in my 12 years of c++ experience I have never looked at the generated assembly of something I wrote. I am probably missing out on some performance somewhere… but I am having no issues meeting some pretty strict performance requirements (DSP and real-time data visualization).