C++ Weekly - Ep 311 - ++i vs i++

Поделиться
HTML-код
  • Опубликовано: 15 сен 2024
  • ☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟
    Upcoming Workshop: C++ Best Practices, NDC TechTown, Sept 9-10, 2024
    ► ndctechtown.co...
    Upcoming Workshop: Applied constexpr: The Power of Compile-Time Resources, C++ Under The Sea, October 10, 2024
    ► cppunderthesea...
    T-SHIRTS AVAILABLE!
    ► The best C++ T-Shirts anywhere! my-store-d16a2...
    WANT MORE JASON?
    ► My Training Classes: emptycrate.com/...
    ► Follow me on twitter: / lefticus
    SUPPORT THE CHANNEL
    ► Patreon: / lefticus
    ► Github Sponsors: github.com/spo...
    ► Paypal Donation: www.paypal.com...
    GET INVOLVED
    ► Video Idea List: github.com/lef...
    JASON'S BOOKS
    ► C++23 Best Practices
    Leanpub Ebook: leanpub.com/cp...
    ► C++ Best Practices
    Amazon Paperback: amzn.to/3wpAU3Z
    Leanpub Ebook: leanpub.com/cp...
    JASON'S PUZZLE BOOKS
    ► Object Lifetime Puzzlers Book 1
    Amazon Paperback: amzn.to/3g6Ervj
    Leanpub Ebook: leanpub.com/ob...
    ► Object Lifetime Puzzlers Book 2
    Amazon Paperback: amzn.to/3whdUDU
    Leanpub Ebook: leanpub.com/ob...
    ► Object Lifetime Puzzlers Book 3
    Leanpub Ebook: leanpub.com/ob...
    ► Copy and Reference Puzzlers Book 1
    Amazon Paperback: amzn.to/3g7ZVb9
    Leanpub Ebook: leanpub.com/co...
    ► Copy and Reference Puzzlers Book 2
    Amazon Paperback: amzn.to/3X1LOIx
    Leanpub Ebook: leanpub.com/co...
    ► Copy and Reference Puzzlers Book 3
    Leanpub Ebook: leanpub.com/co...
    ► OpCode Puzzlers Book 1
    Amazon Paperback: amzn.to/3KCNJg6
    Leanpub Ebook: leanpub.com/op...
    RECOMMENDED BOOKS
    ► Bjarne Stroustrup's A Tour of C++ (now with C++20/23!): amzn.to/3X4Wypr
    AWESOME PROJECTS
    ► The C++ Starter Project - Gets you started with Best Practices Quickly - github.com/cpp...
    ► C++ Best Practices Forkable Coding Standards - github.com/cpp...
    O'Reilly VIDEOS
    ► Inheritance and Polymorphism in C++ - www.oreilly.co...
    ► Learning C++ Best Practices - www.oreilly.co...

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

  • @kobe4460
    @kobe4460 2 года назад +143

    So c++ should've actually been named ++c?

    • @Jonas_Meyer
      @Jonas_Meyer 2 года назад +12

      No the name is for this people that use C++ the same way that they use C.

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

      @@Jonas_Meyer You still need to use regular main() first instead of some static member of a class (like in Java), so first C, then ++ into superset ;)

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

      gah, just made essentially the same comment. It pays to get early notification of videos (and be around to receive them)

    • @Earthcomputer
      @Earthcomputer 2 года назад +24

      It's named C++ because you take C, add to it, then throw away the result and use C

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

      @@Earthcomputer So close, I'd say; start with C, parse new features and COMPILE using C.

  • @marksilverman
    @marksilverman 2 года назад +19

    Once again, I read the title and I thought "I already know everything about that". Then I watched the video and I learned several new things.

  • @necro_ware
    @necro_ware 2 года назад +23

    Couple of years ago I was talking to Andrei Alexandrescu on one event about code optimization. Back then he introduced an interesting code snippet, which was performing quite a lot slower, when using pre-increment instead of post-increment for a simple integer in a loop. It turned out, that using pre-increment in that place enforced the compiler to think, that an increment was important to do before the next operation and it spoiled an important vectorization. A post-increment was much faster, because the compiler was suddenly aware, that an increment can happen at some later point in time and the optimizer did a significantly better job. Well, we all know, that the compilers evolved quite a lot in the last years, but back then, about 6 years ago we both agreed, that it is better to use the post increment for integers and pre-increment for more sophisticated data structures....

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

      Do you remember what the code snippet looked like?

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

      @@mohammedj2941 I must have it in my notes somewhere, I'll try to find it....

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

      ​@@mohammedj2941 Unfortunately I couldn't find my notes anymore. Just too long ago, but I found a code::dive conference 2015 presentation by Andrei on RUclips, where he talks a little bit about this topic. See ruclips.net/video/vrfYLlR8X8k/видео.html It's not exactly the same, what we discussed back then, since it was about vectorization, but the basic idea is very similar.

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

      @@necro_ware Thanks. I'm just impressed that you have notes for code :D

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

      @@mohammedj2941 My interest for compilers woke up as I made my M.Sc. many years ago. Since then I was evaluating a lot of related stuff and I'm always interested in details like this one. That's why I make my notes from time to time, but certainly not always....

  • @Omnifarious0
    @Omnifarious0 2 года назад +35

    I've been trying to get people into the habit of always using pre-increment unless they need post-increment. It's not been easy.
    The iterator to use to demonstrate a big effect would be map.

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

      The default code snippets from visual studio (probably both 2019 and 17 and I didn't test in 2022) for a plain for loop is using the i++. But you are right, pre incr is better in most cases.

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

      It's a shame that compilers can't just optimize it into ++i when it doesn't make a difference regardless of the -O flag.

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

      i once found out the difference between pre and post increment and has been using the prefix version since

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

      @@anon_y_mousse - This is because compilers can't make any assumptions about the relationship between pre and post-increment for overloaded versions of the operators. They may be wholly unrelated.
      This is a problem in general with overloaded operators.

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

      @@Omnifarious0 Indeed. The sad thing is that most libraries don't do anything odd or surprising here, yet the compiler can't make assumptions for those weirdos that use the operators in a "non-standard" way. As in de facto because the standard doesn't dictate that it has to do what a normal person would expect it to do.

  • @treyquattro
    @treyquattro 2 года назад +6

    "unnecessary cognitive overhead" was the most important phrase in this lesson! I try to avoid that at all times.

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

    The use case that comes to mind for post increment is a counter or id generator: return nextId++;

  • @Tyranisaur
    @Tyranisaur 2 года назад +16

    This is C++, where all the defaults are wrong by default. So of course it has the post increment operator in its name, when your default increment should be the pre-version. Granted, you could make the case C++ making sense because of all the compatibility with C.

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

      That's why a part of the C++ community wants to break the ABI. Main problem is still that most of C++ users need it to be retro compatible...

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

      @@kaosce I mean, at some point C++ has to leave the nest right? It can't live in C's basement forever. I've often thought about it and have come to the conclusion that the best option would be to branch off and use C++ as the core of a new language that isn't strictly compatible with C. That way C++ can still maintain it's compatibility with C and continue down that path.
      At the same time though, what benefit would be gained?
      What is it about C that is left to complain about? Macros?
      Really, that's the only thing I can think of that C++ hasn't gotten rid of and until the committee comes up with a way for conditional compilation, they're here to stay. I do wish that people would stop using them for functions/constant expressions though.
      #define DO_STUFF( x )\
      line_1_stuff\
      int y = (x);\
      line_2_stuff
      int main(){
      return DO_STUFF( 42 );
      }
      or
      constexpr int do_stuff( int x )noexcept{
      line_1_stuff;
      int y = x;
      line_2_stuff;
      return y;
      }
      int main(){
      // It's kind of annoying to have to force compile time evaluation though.
      constexpr auto result = do_stuff( 42 );
      return result;
      }

  • @japedr
    @japedr 2 года назад +15

    Well, sometimes it is useful to get the value before the increment without the need to explicitly declare a new variable.
    I'm not advocating for it, but I remember being impressed by the "standard" K&R strcpy:
    void strcpy(char* d, char* s) { while (*d++ = *s++) ; }

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

      This is why post-inc/dec operators exist in C++. They were part of C base that C++ was built on. The construct you have above is probably the reason those operators exist in C language. It's a good reminder that C is less about abstracting programming language away from the machine language and more about doing something very close to machine/assembly but more conveniently and portably. C is more about pointers and less about iterators and objects. Etymology may be important for programming languages too. Perhaps it would be interesting if Jason added more of it to his videos.

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

      I don't really care much for that usage. It's too busy and is difficult for an inexperienced programmer to reason about. You have to know the order of operations/precedence order to make sense of it. Sure, once you have a good grasp of the language it makes sense, but every time I saw someone write this I cringed.
      There's so much going on:
      dereference d
      store d_reference
      increment d
      dereference s
      store s_reference
      increment s
      assign the value of s_reference to the value of d_reference
      test if d is NULL
      loop or break
      return
      The C language itself may not support reference semantics like C++, but dereferencing a pointer and assigning to it is basically the same thing as assigning to a C++ reference, otherwise this code would not actually assign anything the destination char array.
      Cramming all that in such a small amount of code requires some mental gymnastics to decipher. I prefer the more expressive 'for' loop personally.
      for( ; ( s != NULL ) && ( d != NULL ); ++s, ++d )
      {
      *d = *s;
      }
      Might be more verbose, but much easier to understand what's going on.

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

      @@MrAlbinopapa Or the form I use: int i; for ( i = 0; s[i]; i++ ) d[i] = s[i]; and you get to play with `i` after the loop too.

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

      The thing is that today the compiler will remove the variable, so there is literally no reason not to explicitly make a placeholder variable for readability if your intention was to use that pre-incremented value. The resulting code is going to be the same, just one harder to read.

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

      @@anon_y_mousse in a for loop, the i++ is a statement on it's own, so the temporary would be created, not used, discard, enter the loop body again (it wouldn't be called the first time entering the loop), and then the incremented value is what you are using as the index in the next iteration of the loop. The compiler automatically converts it to ++i, since that temp is never able to be used.

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

    i+=1; use i; is a ++i.
    use i; i+=1; is a i++.
    With the optimization, i+=1, ++i without using i, i++ without using i are the same.
    All the 3 cases are useful. Especially when dealing with the iteration.

  • @Possseidon
    @Possseidon 2 года назад +17

    I'd argue, if the return value isn't used (which is often the case), semantically it doesn't make a difference. You're neither using the old nor the new value, so both ++i and i++ make perfect sense. Both do something extra besides the increment (albeit i++ being less optimizable in some cases).
    Personally I'm still using i++ out of habit, especially when I know that I'm just incrementing some primitive type anyway and there literally won't be any difference.
    Just my take on it, who knows, maybe I'll actually switch to ++i at some point.

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

      It doesn't really matter if the return value is used or not - you still asked the compiler to do something very specific, and it still has to deal with that.
      Ultimately the optimizer usually takes care of it, of course.

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

    I migrated too many `for(int i; i < count; i++)` to iterator based `++it` loops. So I try to teach to almost always use pre increment, even for for-ints "where it doesn't matter", just to get this muscle memory set up early.

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

      Same, micro-optimizations FTW! LOL. I've had to explain this to some people for why I prefer using:
      auto variable = Type{}
      instead of
      Type variable{}.
      This forces me to think about const correctness. Though, the only time I find it annoying is declaring a pointer I'm not ready to initialize yet.
      Type* pVariable1 = nullptr;
      auto* pVariable2 = reinterpret_cast(nullptr);
      auto* pVariable3 = (Type*)nullptr;
      // ... initialization may be handled in a block like if or for statement

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

      Then there is me who learned to use the for loops, to then while(--count):P

  • @jhbonarius
    @jhbonarius 2 года назад +23

    Similarly, we almost never mean "increment and return the new value", we just mean "increment".

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

      Go chooses the former - increment exists but only as a statement, it can't be used as an expression, (and so only one operator is provided, there being no difference remaining)
      Swift genuinely did abolish them. Both pre-increment and post-increment used to exist in older versions of Swift and then they were removed.

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

      That’s not really true. Increment and capture is used all the time when you need to immediately use next anyway. It’s certainly more common than correctly using post-increment. That’s mostly used for cute things like last_itr = current++;.
      But yes, a lot of languages just decided the increment operators are confusing when a += 1 gets the job done as well (of course some languages also think the combined operator-assign is also confusing, so you just get a = a+1)

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

      @@zyzzyxdonta OMG, NO!!!. I hate writing i = i + 1; apple = apple + i;
      I'd much rather write apple = ++i; or apple = i++;
      There are a few times I've found myself initializing an array where It couldn't be initialized in a loop. Being able to increment an index within the subscript operator ( operator[] ) makes code more condense and still readable.
      int int_array[ 4 ];
      int i = 0;
      int_array[i++] = 7;
      int_array[i++] = 6;
      int_array[i++] = 4;
      int_array[i++] = 2;
      Otherwise:
      int_array[i] = 7;
      i = i + 1;
      int_array[i] = 6;
      i = i + 1;
      int_array[i] = 4;
      i = i + 1;
      int_array[i] = 2;
      C/C++ has spoiled me.

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

      @@MrAlbinopapa What about simply
      int_array[0] = 7;
      int_array[1] = 6;
      int_array[2] = 4;
      int_array[3] = 2;

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

      @@vytah The only reason I might choose: int_array[ i++ ] is for the ability to copy/paste a bunch and only have to change the right side of the '='. Another reason might be for loop unrolling. Of course, with loop unrolling my preferred method would be:
      for( int i = 0; i < count; i += 4 )
      const int j = i * 4;
      int_array[ j + 0 ]
      int_array[ j + 1 ]
      ... and so on, but that could just be j++ for each instead.

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

    There are tons of use cases for using post-increment. A lot of them are in address arithmetic, when you need to do something with data by pointer before increment pointer. Good example is a canonical strcpy implementation:
    while(*strDest++ = *strSrc++);

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

    Should post increment be marked [[no_discard]] ? Maybe I can't see a situation where you would want to skip using the return value of post increment

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

      With all of my current code I do mark it [[nodiscard]]

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

    Been using pre-increment for years now. It just makes more sense. I made myself a guideline to always use pre-increment and leave a comment when I use post-increment of why I used it. I might just ban myself from using post-increment altogether, it may be more verbose but I think it's more clear.

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

      @@richardlyman2961 You're damn right I'm a nerd. 🤓 ...But I think I was also drunk when I wrote that so my tweeb side shines extra hard. XD
      But to answer your question, it's more efficient to think things through once, break it down to a list of rules and train yourself to those. You'll make less mistakes and you'll be faster.

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

    furthermore even if the compiler optimizing is good I guess it's better to have a code closer to what we really want (for semantic) but also to improve compilation performance (compiler does not have to optimize i++ into ++i if we already wrote ++i). This might be meaningfull only in large codebase ofc.

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

    I wonder if I should just write i += 1, because that's usually what I mean. I would never try to use a return value from increment operator, it requires too much thinking no matter whether you actually want pre or post increment. And if I actually want the previous value I would just store it in a temp so it's clear what I actually return.

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

      that's what python does. no meaningless post vs pre increment discussions there.

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

      I've been recently writing i += 1; everywhere except for the for loop increment part, where I stick to the traditional i++ just for sake of tradition. The ++ operator is a relic of the 60s, when compilers were really dumb, there's a reason modern languages do not have anything like it anymore.

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

      If you're writing generic code that might operate on iterators; then I believe forward iterators would require an increment operator; not arithmetic

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

      @@DaveWhipp I recently tried unordered_map iteration and there it works, but I agree it would probably not be guaranteed to work. Usually I use "for auto" though, so I don't have to handle manual increment for most iterations.

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

      Swift started out having C's pre-and-post increment operators, but then got rid of them after they got rid of C style for loops. Since it turned out C-style loops were the only place in Swift where people were even using those operators.
      Meaning they have to use `i += 1` when they want to increment an integer. Of course, they have a different iterator model than C++.

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

    So in the post-increment version of the my_int the value++ should be replaced by ++value, since within the operator

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

      *operator++(int)

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

    I find pre-increment vs post-increment discussions funny because while technically pre-increment is what we mean and should be using, in practice it rarely ever matters. I almost never use increment and decrement operators in complex expressions so the code returning original value is optimized away and when I do use increments in expressions it's usually for low level code like array[index++] = value; where I actually mean to use the post-increment operator. In C++ I rarely need that because I almost always have vectors with push_back() or other containers with their corresponding methods. Still, it's definitely an interesting aspect of C/C++ that is worth learning about.

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

      After a discussion on Twitter (thanks, @beached_whale), a good use case for post-increment is in return statements. Maybe your increment operators have a side effect you want to take advantage of (for some reason) or you're incrementing a reference so the increment itself could be a side effect of sorts, but you want to return whatever was held prior to the increment.

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

      Also use `emplace_back` over `push_back` to construct the new value in-place :)

  • @Raspredval1337
    @Raspredval1337 2 года назад +6

    Most pre-increment defenders I've seen almost always give the for loop example. Which is dubious, because any sane compiller would get rid of indexing completely, and replace the whole constuct with something based on pointer increment and dereferencing. In most cases, pre and post increments are optimized, unless they're a part of some expression. But at that point it's probably done with actual intent, and not as lazy way to increment a variable

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

    In the beginning of autovectorization, there were differences, where the (gcc) compiler was able to detect loops with i++, where it did not found it with ++i. I just had a go and all compilers were able to detect it properly. Similar with the vectorization of a reverse for loop: for (size_t i = n; i--;)
    Edit: mixed up i++ and ++i.
    Edit 2: Just saw Necroware gave essentially the same comment.

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

    By far the most common use-case I've encountered for post-increment is by indexing an array and increasing the index where the index was initialized to zero. If I'd use the pre-increment, the first index used would be one instead of zero:
    my_array[index++] = ...

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

      but there's a for loop to increment the index. And most compillers would actually prefer (and optimize the crap out of) the for loop, just saying

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

      @@Raspredval1337 this is more common on while loops

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

      ​@@Raspredval1337 You can't increment in a loop if the operation involving the increment is conditional. For example, if you're copying values that satisfy a predicate.

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

      @@Raspredval1337 the use-case that Alex Warhawk demonstrated does not need to be inside a loop. I recently "defended" on of my colleagues at work when others were saying he should have written it like array[index] = ...; ++index; I think it is a rare case, but here it totally made sense.

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

      @@fl4shi238 splitting the two operations is fine too. At that point it's just conventions.

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

    If you write code less efficient as it can be but the optimizer makes it as efficient as it can be... is you code less efficient?
    I mean, I understand that is not good practice to depend on optimizers but my cuestion I think is still valid.

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

      If you use it in hot loops and need to debug using an unoptimized debug build it might make a significant difference.

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

    Usually post increment helps a lot to shorten the code. For example, in your example you could have had: while (begin++ != end) { // your code here, but already without ++begin; }

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

      Same idea: you are specifically asking for the "old value"
      But I strongly avoid code like that as I find it makes it harder to read and maintain more often than it helps.

  • @embeddedbastler6406
    @embeddedbastler6406 2 года назад +6

    In startup code there is often code like
    while(data < &_edata)
    *data++ = *dataInit++;
    Using pre-increment would certainly be less fancy.

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

      I never said don't use post increment, I just said to know what you are asking for. In code like that it was clearly a choice to make the choice more succinct.
      Put a different way, I would argue that post increment should be [[nodiscard]]

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

      Even better `while (*dest++ = *src++) /*nothing*/;` :>

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

      @@von_nobody this is only for null-terminated data.

    • @93davve93
      @93davve93 2 года назад +1

      Why not just be clear and explicit? Expand the loop and add an index variable. Better to have clear code that is less prune to bugs imo. :)

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

      @@93davve93 this pattern is already clear and very common in C code.

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

    even if you want to use the old value and also increment, usually you can do those on 2 lines in that order and save the copy.

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

    You use `const auto previous = *this;` and I’d argue that previous should not be const because if NRVO is not performed you are forcing a copy rather than a move.

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

      You're right, but at the same time, we can almost 100% count on NRVO.
      And on the other hand a better solution could probably have been implemented with std::exchange.

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

    For the take-away point, I'd say that it is not post-increment or pre-incremwnt that should raise concerns, but assigning their result to something.
    Since if you're not assigning the result, the optimiser will most likely make sure that there is no difference.

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

    I didn't know that the current state was both are optimized similarly (at least for cheap iterators I guess), but in general I have the same conclusion and way to see it than you, so basically we are in strong agreement :)

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

    I've almost always used ++i in for loops, etc. Mainly for the iterator thing (I think Sutter wrote about it like 20 years ago), but semantically it's just more correct. Always irks me a little that example code everywhere uses i++.

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

      Lua is a good philosophy on how you should sit down and design a language. I forgot where but I remember Mr Lerusalimschy posted how C was implemented iand wanted to avoid it by not having it. Part of the reasons it was kept in the standard was l33t hackers want to do crazy pointer math. The only reason to keep it is because of the C macro language that by god, if you don't have it, half the world will die.

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

      @@warlockd Okay, so you can't understand why you should leave a language feature the way it always was to keep from breaking legacy code. And you also can't understand that for legacy programmers they had limitations that made such features essential to do their job. Nor do you understand what macros are, in C or otherwise apparently because it's not a part of macro syntax in C. Don't ever design a programming language, especially one that has even the vaguest hint of an idea of being backwards compatible with anything else.

  • @SillyOrb
    @SillyOrb 27 дней назад

    I default to "variable += 1". Its intention is unambiguous. There's no second guessing the code months and often years later, whether the right ++ is used. It's also more flexible, but that's a rarely used niche detail.
    Why was C++ the "correct" name indeed at least in its early days?
    Because its first compiler Cfront had actually translated C++ code to C and then that was compiled instead. So we could say that C++ "returned the previous value" in form of its predecessor C. Admittedly, you have to mentally squint very hard to make this appear coherent. Although this "clever" idea (Was it even intentional? I don't know.) didn't last long, as native C++ compilers were created, and this little factoid seems to have largely faded into obscurity.

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

    Well, that's the same as for using `int` in loops, like you did in this episode. My question for using `int` in this case is also "why" if we don't need any negative values for the counter? But many people anyway use `int` as a counter because... Why?

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

      Because with int you can easily reverse the loop direction like this.
      for(int i = n-1; i >= 0; --i) {}
      If you have a size_t instead of int, and you write it like this, you will get an infinite loop. The compiler almost never warns about this.

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

      There is a C++ Core Guideline that says one should only use unsigned for bitwise operations and similar and use signed types for math. The main reason is that unsigned is allowed do over-/underflow without being UB. This can result in unexpected results and also poor compiler optimization. I think there is a C++ Weekly episode about the optimization part as well.

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

    No offense, but it's weird you cannot find a use in post increment... and code fibo with std::exchange....
    i++ is just a simpler form of std::exchange(i,i+1) :-)

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

      I don't recall saying I couldn't find a use for it. I said it's almost never what you mean.

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

    seems like this is getting the obligatory "does it really matter" sort of comments jason was expecting... whenever i see post-increment where its not needed i recoil in horror, throw my hands in the air and shout at my screen, WOW, you really dont even know the difference between pre and post increment operators?! i immediately cant trust the entire codebase because it was clearly written by a 5 year-old. thats what "really" matters.

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

      Lol, I feel the same about several code choices. Sometimes the code can look soooo clean, then stumble across i++, or see C++11 or higher features yet still use unscoped enums with the enum name prefixing the enumerators. I mean, you've already broken C compatibility by using the C++ features, why not keep going? Or using enumerators as constant expressions. Watched a YT creator that was teaching C++, then proceeded to use const char* instead of std::string. I know before C++17's std::string_view for string literals it makes sense to pass a const char*, unless you're logging ( writing to file or console ) it makes more sense to teach C++ using the C++ library and stop teaching operators new/delete. If there was ever any user facing feature to remove it would be the global new/delete operators.
      Wow, I really got off on a tangent there.

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

      That's a childish response. i++ looks better than ++i and if the compiler is set to optimize, it really doesn't matter in every context unless you're using the value at the same time as incrementing. You really shouldn't use the value at the same time as incrementing, but if you're going to do that, you should know what you're doing. In fact, you absolutely should not have rules that are absolutes, except when you should.

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

      bruh. respect my pronoun. racist

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

    Should we rename it ++C instead of C++?

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

    Why do you have constexpr on the methods? Cheers.

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

      Probably not necessary in this example, but it's good practice to have that in the signature. For one, he wrote a book about "best practices", so it wouldn't look good to not practice what you preach. Also, constexpr functions can only call other constexpr functions, so while not used here, if he were to have another function declared with constexpr he wouldn't be able to call it inside this function unless it was also constexpr regardless if it was compile time evaluated or not.

  • @madpuppet666
    @madpuppet666 6 месяцев назад

    all I have to say is
    *dest++ = *src++

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

    when using iterators I use ++i, but usually just use i++ for any primitive idk why, just habit I guess :/

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

    Well, you see, with the post-increment you can simplify to
    result += begin++->second;
    skipping the
    ++begin;
    line.

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

    I think it changes nothing. Still, please use ++i, or better use a range for loop, because it triggers me for no reason.

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

    I really don't use for loops anymore but in the past I've seen indiscriminate changing of i++ to ++i sometimes causing problems. I have always used i++ and even more when dealing with pointers. When looking at it from a class operator perspective ++i seems to be simpler in every case. However, when thinking of an Out of Order Processor scheduling operations the post operation may seem advantageous, use the value then schedule the increment. For the most part the compiler will find a way which makes everything moot. It is somewhat gratifying when you mix a *i++ with a +1 producing a *i+++1.

  • @AnimeLover-su7jh
    @AnimeLover-su7jh 2 года назад

    I guess it might have been useful if you discussed the operator precedence for them, because there are difference if you are using complex expression (like, arrow operator and pre-increment and de-referencing and so on)

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

    Would be great to also show the difference between:
    x = y++
    and
    x = y
    ++y
    on some more complex types.

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

      Same for :
      Array[i++] = complex_operation();
      vs
      Array[i] = complex_operation();
      ++i;

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

    I have used post-increment (deliberately) . I don't remember exactly but it was a case in which the loop counter was not zero but the result of some computation eg while (someArray[x++] > somethingElse) {}. Had I used pre-increment, I would corrupt the previous computation. I must admit it looks more 'C' ish than 'C++'ish. I suspect programmers who have had to define operator++ will be more familiar with differences between pre and post; especially if they had to override post-increment.

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

    I knew there were some performance difference in both but didn't exactly knew what was causing it.

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

      Now here's a question, is there a performance penalty in using the subscript operator vs incrementing an iterator or pointer?
      // subscript operator
      for( int i = 0; i < array.size(); ++i ){
      auto const& value = array[ i ];
      }
      for( auto it = array.begin(), end = array.end(); it != end; ++it ){
      auto& value = *it;
      }
      Type* values = array.data();
      for( auto* it = values, end = values + array.size(); it != end; ++it ){
      auto& value = *it;
      }
      I did this test a few years ago on a computer that was built back in 2009. There doesn't seem to be much of a performance penalty using indices. I guess in the early days of computer architecture or compilers or both, indexing was noticeably slower and incrementing a pointer then dereferencing was faster.
      So either because of architecture improvements or compiler optimizations, there's really no significant difference in performance. The only real difference is using iterators with the post increment because of the added 'cargo' they need to check if they are out of bounds and from the same container for comparisons.

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

      @@MrAlbinopapa i don't think there might be a performance difference, even i tried large computation using ++i and i++ and saw no difference

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

      @@segsfault compilers have gotten pretty good over the years and there might even be cases where the c++ language is helping. Guaranteed copy elision when returning a temporary and copy initialization.
      Auto count = i++;
      If the post increment is an operator overload, no copy happens, assuming count fits in a register the old value of 'i ' is directly created in the register assigned to 'count'

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

      It really is unlikely to ever have a performance difference you can measure. My main point was to get you thinking about the meaning of the code.

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

      @@cppweekly Yeah, this is just of those features you have to "know" about to use it correctly. Which I guess if that's the case I understand why, as others have said, other languages don't implement it. Myself, I have been using prefix for almost everything even when it doesn't matter. The only exception is inside a subscript operator.

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

    When you have defined the post-increment operator, you wrote value++ instead of ++value :P

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

      This was 100% intentional. I wanted to model the behavior of the existing code in the extremely unlikely chance that the contained type did something "unusual."
      doesn't matter for an int, of course. But in generic code this could matter.

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

    Sometimes I even see (void)++i Guess some people don't trust the optimizer anymore :D

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

    So we should rename C++ to ++C, because only this make senses!!!

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

    I'm an adherent of pre-increment, so much so that I call the language ++C...

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

    As *statements*, i++ is interchangeable with ++i and has no difference whatsoever since the returned i is never used. Arguing otherwise is like saying you should write code differently because in debug builds the compiler is dumb.
    As *expressions*, I think i++ is used more often in my experience. It's very useful when appending things to an array. For instance, `
    int i = 0;
    int filtered[ARRAY_LEN];
    for (T elem : data) {
    if (elem.insert && i < ARRAY_LEN) {
    filtered[i++] = elem.value;
    }
    }
    // i = length of filtered at end of loop
    `

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

      > has no difference whatsoever
      But it is fundamentally different, which was the point of this video. the compiler has to deal with the fact that you explicitly asked it to copy the old value and return that back to you.

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

    A case of post increment can be where we want to use present value and increment it in next iteration this might be useful in case where we are iterating over map of map (or other collection) and need to iterate over a few elements and not all the elements
    Like this
    void display(const auto & coll) {

    // we want to use present value and increment it in next iteration
    auto it = coll.cbegin() + 5;
    while(coll.cend() != it) {
    std::clog

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

    One might reasonably ask why the increment operator returns a value at all. The only answer seems to be that with the exception of *delete,* all other operators return something. And of course, that it was inherited from C.
    While I occasionally find myself trying to use it, anyway, I kind of like Python's solution to this: just don't have one. Once you stop using indexes and manual iterators for things, single incrementing really doesn't come up that often.

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

    i += 1 :P

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

      A place where I interned during college, had a coding guideline to explicitly write i=i+1 instead of i++ or ++i, for the module I was working with. The story was that their vendor had to recall a large inventory of electronics because of a bug that was traced to a misplaced post-incrementor, and they were able to forward the blame and liabilities, fines, on the company I was intern at.

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

      @@AbhinavKulshreshtha lol.. it seems to me the problem was the lack of tests to catch the bug

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

      @@frydac I don't know. It was the story behind the weird coding guidelines. It should have been an edge case though. Just as explained in this video, increment operator has an unexpected mechanism. This exact same thing was taught to us at internship, but my college academics rejected this concept.

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

    CS Student here, now I inwi what they mean that no one is an expert in C++ lmao.

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

    COUNTERPOINT: The name of the language is "C++".
    OK, OK, I'll start using pre-increment.

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

    Then...C programmers are actually programming in C++!

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

    I *humbly* suggest that your interpretation : "give me the previous value" is slightly off.
    A more accurate interpretation is : give me the the current value then increment and store the new value.

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

      Except there's no way to model that in C++. You have to make a copy of the old value, then increment the current value, then return the old value.

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

    There is another way of writing i++ that makes its purpose clear:
    for (i=0; i

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

      It's interesting that older compilers used to do that - I had not see or heard of that before. But I don't think "because old broken compilers used to compile this wrong" is a good reason today, unfortunately.