Author Topic: Preincrement (++x) vs Postincrement (x++)  (Read 2763 times)

0 Members and 1 Guest are viewing this topic.

JohnK

  • Administrator
  • Seagull
  • Posts: 10638
Preincrement (++x) vs Postincrement (x++)
« on: January 12, 2016, 02:26:39 PM »
I'm watching this tutorial by some guru and he keeps using postincriment. ...he even touched on the topic saying that "they are essentially the same so he prefers to use postincriment because it's what he does in real code.". This is a microscopic level detail annoyance fro me and his loops are really starting to get on my nerve.

Basically, postincriment makes a copy, returns it and incriments the original. ...long story made short, just use preincriment because the semantics of how postinc plays out can come into play--especially in C++ and other low level languages--so it's better to develop good habits and never have to work yourself out of that rabbit-hole.

Code - C#: [Select]
  1. for (uint x = 0; x < 10; ++x) {
  2.     // do something
  3. }
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

huiz

  • Swamp Rat
  • Posts: 917
  • Certified Prof C3D
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #1 on: January 13, 2016, 07:09:01 AM »
Well, that makes sense now. Once I wanted to add a number to an incremental list but didn't want to start at zero, so I did this:

Code: [Select]
int i = 0;
foreach (Item item in Items) {
 print string.format("Item {0}", i++);
}

I expected that i++ would be handled first, so it should become 1 before the first item got printed. But it started at 0.

I'll test it wit ++i to see if that is the trick :-)
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

JohnK

  • Administrator
  • Seagull
  • Posts: 10638
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #2 on: January 13, 2016, 08:57:27 AM »
You will almost never get in deep water using preincriment and to be clear, where the problems start with postincriment is when dealing with iterators.

Your choice of using a foreach with a counter starting at zero (but you really want the first item to be one) is kinda confusing. Maybe you could start your counter at 1 and use a do while loop?

Also, if you wanted to be very picky about the code you posted I would also suggest using a unsigned int (uint) as well. This is one of the things that I, personally, try to be very diligent about (using proper types where needed); I've gotten in to trouble several times being sloppy with my types. -e.g. I went and created a program with base and derived classes all over the place using STRING when I should have been using a combination of string and char[] (this was in C++). I spend more time going through my program fixing all the mistakes and recoding the proper methods then I did writing the program. That is when I made myself to always try to be a little more mindful of the types I *NEED* and what I am *USING*. Like in the example you gave; the counter (i) will never be negative, so I'd use an unsigned int.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #3 on: February 01, 2016, 04:11:20 AM »
while I'm still practicing my C chops :)

Code - C++: [Select]
  1. #include <stdio.h>
  2.  
  3. int main(int argc, char *argv[])
  4. {
  5.         int x = 3;
  6.         int y;
  7.         int z;
  8.  
  9.         y = ++x;
  10.         printf(" y(++x) = %d\n x = %d\n", y, x);
  11.  
  12.         x = 3;// reset x
  13.         z = x++;
  14.         printf(" z(x++) = %d\n x = %d\n", z, x);
  15.  
  16.         return 0;
  17. }

Output:
Quote
y(++x) = 4
 x = 4
 z(x++) = 3
 x = 4
Press any key to continue...
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2139
  • class keyThumper<T>:ILazy<T>
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #4 on: February 01, 2016, 06:27:12 AM »
Ditto for C# ... but you knew that :)

Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

JohnK

  • Administrator
  • Seagull
  • Posts: 10638
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #5 on: February 01, 2016, 03:56:51 PM »
Like I said, post/preincriment is very micro-level stuff and the use of postincriment only really matters when dealing with iterators. You will never get in trouble using preincriment, so that's just what I prefer to use. ...Here is a quick test I built to show time differences but it doesn't really do a very good job at that so take take what you will from it (feel free to ignore).

Code: [Select]
UNSIGNED ints
123
PostIncriment (unsigned): This operation took: 0.0005363 seconds.

123
Preincriment (unsigned): This operation took: 0.0001453 seconds.


STD::STRING
one two three four five six seven eight nine ten
Postincriment (string): This operation took: 0.0014165 seconds.

one two three four five six seven eight nine ten
Preincriment (string): This operation took: 0.0014661 seconds.


Custom STRING (MSTRING)
         - A fast string implementation with a maximum of 8 characters
one two three four five six seven eight nine ten
Postincriment (mstring): This operation took: 0.0014406 seconds.

one two three four five six seven eight nine ten
Preincriment (mstring): This operation took: 0.0014739 seconds.

Code: [Select]
UNSIGNED ints
123
PostIncriment (unsigned): This operation took: 0.0005591 seconds.

123
Preincriment (unsigned): This operation took: 0.0001560 seconds.


STD::STRING
one two three four five six seven eight nine ten
Postincriment (string): This operation took: 0.0014712 seconds.

one two three four five six seven eight nine ten
Preincriment (string): This operation took: 0.0015229 seconds.


Custom STRING (MSTRING)
         - A fast string implementation with a maximum of 8 characters
one two three four five six seven eight nine ten
Postincriment (mstring): This operation took: 0.0015286 seconds.

one two three four five six seven eight nine ten
Preincriment (mstring): This operation took: 0.0014517 seconds.

Code: [Select]
UNSIGNED ints
123
PostIncriment (unsigned): This operation took: 0.0008900 seconds.

123
Preincriment (unsigned): This operation took: 0.0002601 seconds.


STD::STRING
one two three four five six seven eight nine ten
Postincriment (string): This operation took: 0.0027534 seconds.

one two three four five six seven eight nine ten
Preincriment (string): This operation took: 0.0025759 seconds.


Custom STRING (MSTRING)
         - A fast string implementation with a maximum of 8 characters
one two three four five six seven eight nine ten
Postincriment (mstring): This operation took: 0.0025534 seconds.

one two three four five six seven eight nine ten
Preincriment (mstring): This operation took: 0.0028705 seconds.


Source (minus the custom classes and stuff).
Code - C++: [Select]
  1. #include "D:\Programming\C++\projects\include\pctimer.h"
  2. #include "D:\Programming\C++\projects\include\mstring.h"
  3.  
  4. int main () {
  5.     std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
  6.     pctimer_t t1, t2;
  7.     t1 = pctimer();
  8.  
  9.     // UNSIGNED
  10.     //
  11.     std::cout << "\nUNSIGNED ints" << std::endl;
  12.  
  13.     std::vector<unsigned> items;
  14.  
  15.     items.push_back(1);
  16.     items.push_back(2);
  17.     items.push_back(3);
  18.  
  19.     for (std::vector<unsigned>::iterator i = items.begin(); i != items.end(); i++) {
  20.         std::cout << *i;
  21.     }
  22.  
  23.     std::cout.precision(7);
  24.     t2 = pctimer();
  25.     std::cout << "\nPostIncriment (unsigned): This operation took: " << t2 - t1 << " seconds.\n\n";
  26.  
  27.     // Reset the timer.
  28.     t1 = pctimer();
  29.  
  30.     for (std::vector<unsigned>::iterator i = items.begin(); i != items.end(); ++i) {
  31.         std::cout << *i;
  32.     }
  33.  
  34.     std::cout.precision(7);
  35.     t2 = pctimer();
  36.     std::cout << "\nPreincriment (unsigned): This operation took: " << t2 - t1 << " seconds.\n\n";
  37.  
  38.     // STD::STRING
  39.     //
  40.     std::cout << "\nSTD::STRING" << std::endl;
  41.  
  42.     std::vector<std::string> string_items;
  43.  
  44.     string_items.push_back("one");
  45.     string_items.push_back("two");
  46.     string_items.push_back("three");
  47.     string_items.push_back("four");
  48.     string_items.push_back("five");
  49.     string_items.push_back("six");
  50.     string_items.push_back("seven");
  51.     string_items.push_back("eight");
  52.     string_items.push_back("nine");
  53.     string_items.push_back("ten");
  54.  
  55.     // Reset the timer.
  56.     t1 = pctimer();
  57.  
  58.     for (std::vector<std::string>::iterator i = string_items.begin(); i != string_items.end(); i++) {
  59.         std::cout << *i << " ";
  60.     }
  61.  
  62.     std::cout.precision(7);
  63.     t2 = pctimer();
  64.     std::cout << "\nPostincriment (string): This operation took: " << t2 - t1 << " seconds.\n\n";
  65.  
  66.     // Reset the timer.
  67.     t1 = pctimer();
  68.  
  69.     for (std::vector<std::string>::iterator i = string_items.begin(); i != string_items.end(); ++i) {
  70.         std::cout << *i << " ";
  71.     }
  72.  
  73.     std::cout.precision(7);
  74.     t2 = pctimer();
  75.     std::cout << "\nPreincriment (string): This operation took: " << t2 - t1 << " seconds.\n\n";
  76.  
  77.  
  78.     // CUSTOM STRING (MSTRING)
  79.     //
  80.     std::cout << "\nCustom STRING (MSTRING)" << "\n\t - A fast string implementation with a maximum of 8 characters" << std::endl;
  81.     std::vector<mstring> mstring_items;
  82.  
  83.     mstring_items.push_back("one");
  84.     mstring_items.push_back("two");
  85.     mstring_items.push_back("three");
  86.     mstring_items.push_back("four");
  87.     mstring_items.push_back("five");
  88.     mstring_items.push_back("six");
  89.     mstring_items.push_back("seven");
  90.     mstring_items.push_back("eight");
  91.     mstring_items.push_back("nine");
  92.     mstring_items.push_back("ten");
  93.  
  94.     // Reset the timer.
  95.     t1 = pctimer();
  96.  
  97.     for (std::vector<std::string>::iterator i = string_items.begin(); i != string_items.end(); i++) {
  98.         std::cout << *i << " ";
  99.     }
  100.  
  101.     std::cout.precision(7);
  102.     t2 = pctimer();
  103.     std::cout << "\nPostincriment (mstring): This operation took: " << t2 - t1 << " seconds.\n\n";
  104.  
  105.     // Reset the timer.
  106.     t1 = pctimer();
  107.  
  108.     for (std::vector<std::string>::iterator i = string_items.begin(); i != string_items.end(); ++i) {
  109.         std::cout << *i << " ";
  110.     }
  111.  
  112.     std::cout.precision(7);
  113.     t2 = pctimer();
  114.     std::cout << "\nPreincriment (mstring): This operation took: " << t2 - t1 << " seconds.\n\n";
  115.  
  116.     return 0;
  117. }
  118.  
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #6 on: February 01, 2016, 04:02:04 PM »
a possible explaination of the time differences:

http://www.embedded.com/design/programming-languages-and-tools/4410601/Pre-increment-or-post-increment-in-C-C-

Quote
<snip>...
Imagine that we were defining the int data type (only we will call it Integer) from scratch in C++. We might have something like this:

class Integer
{
  public:
  Integer& operator++()
  {
    x_ += 1;
    return *this;
  }
  const Integer operator++(int)
  {
    Integer temp = *this;
    ++*this;
    return temp;
  }
  private:
  int x_;
};

The additional storage for the post-increment, temp, is clear.

In a real implementation of a complex data type (a class), the overhead may be much greater than just the additional word of storage and a little extra code.

Of course, a smart compiler would almost certainly pick this up and optimize the unnecessary storage away. It is, however, much better to understand the semantics of the language and write defensively – code exactly the functionality that you intend and do not rely on a compiler to make up for your shortcomings.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

JohnK

  • Administrator
  • Seagull
  • Posts: 10638
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #7 on: February 01, 2016, 04:06:11 PM »
Nice!
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #8 on: February 02, 2016, 01:49:37 AM »
ASM is the same, vs2015

Code - ASM: [Select]
  1. ; 16   :     int A = 0;
  2.  
  3.         mov     DWORD PTR A$[rbp], 0
  4.  
  5. ; 17   :     int B = 0;
  6.  
  7.         mov     DWORD PTR B$[rbp], 0
  8.  
  9. ; 18   :
  10. ; 19   :     A++;
  11.  
  12.         mov     eax, DWORD PTR A$[rbp]
  13.         inc     eax
  14.         mov     DWORD PTR A$[rbp], eax
  15.  
  16. ; 20   :     ++B;
  17.  
  18.         mov     eax, DWORD PTR B$[rbp]
  19.         inc     eax
  20.         mov     DWORD PTR B$[rbp], eax
  21.  

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Preincrement (++x) vs Postincrement (x++)
« Reply #9 on: February 03, 2016, 12:01:16 PM »
Like in the example you gave; the counter (i) will never be negative, so I'd use an unsigned int.


Myself I would use var and let the compiler figure it out.  If by chance I would ever need the counter to go over the maximum value of int then I would use uint or even uint64.


If you really wanted to be picky and you were only using it for a counter and you knew the maximum amount of items were less than 32,767 then you should use a unsigned short and not an uint.  If you are really being picky that is.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013