Thread: Can someone explain this C++ example to me?

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    Can someone explain this C++ example to me?

    Here's the link : c++ - How to make elements of vector unique? (remove non adjacent duplicates) - Stack Overflow

    I get that insert() returns a pair of <iterator, bool> which is fine so I get what set.insert().second is. It's true if we insert, false if there is a duplicate.

    But I'm having trouble understanding how this vector is re-writing itself. For example, here's some code with extra address information and it's not adding up.
    Code:
    #include <vector>
    #include <set>
    #include <iostream>
    using std::cout; using std::endl;
    int main(int argc, char* argv[])
    {
        std::vector< int > k ;
    
    
        k.push_back( 2 );
        k.push_back( 1 );
        k.push_back( 6 );
        k.push_back( 1 );
        k.push_back( 4 );
        k.push_back( 6 );
        k.push_back( 2 );
        k.push_back( 1 );
        k.push_back( 1 );
    
    
       for (unsigned i = 0; i<k.size(); i++)
          std::cout << "Original addresses : " << &k[i] << ", Value : " << k[i] << std::endl;
    
    
    std::cout << "\n" << std::endl;
    
    
    {
    	std::vector< int >::iterator r , w ;
    
    
    	std::set< int > tmpset ;
    
    
    	for( r = k.begin() , w = k.begin() ; r != k.end() ; ++r )
    	{ 
    
    
    
    
    
    
    		if( tmpset.insert( *r ).second )
    		{ 
    			*(w++) = *r ;
    
    
    		}
    
    
       cout << "Address of r : " << &(*r) << ", Value : " << *r << endl;
       cout << "Address of w : " << &(*w) << ", Value : " << *w << endl;
    
    
       for (unsigned i = 0; i<k.size(); i++)
          std::cout << "Original addresses : " << &k[i] << ", Value : " << k[i] << std::endl;
    
    
    std::cout << "\n" << std::endl;
    	}
    
    
    	k.erase( w , k.end() );
    }
    std::cout << "\n" << std::endl;
    
    
        {
        	std::vector< int >::iterator r ;
    
    
        	for( r = k.begin() ; r != k.end() ; ++r )
        	{
        		std::cout << "(" << &(*r) << ", *r)" << (*r) << std::endl ;
        	}
        }
    }
    Basically, I just don't get this output :
    Code:
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd080, Value : 2
    Address of w : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd084, Value : 1
    Address of w : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd088, Value : 6
    Address of w : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd08c, Value : 1
    Address of w : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 1
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd090, Value : 4
    Address of w : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 4
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd094, Value : 6
    Address of w : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 4
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd098, Value : 2
    Address of w : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 4
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd09c, Value : 1
    Address of w : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 4
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    Address of r : 0x1bcd0a0, Value : 1
    Address of w : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd080, Value : 2
    Original addresses : 0x1bcd084, Value : 1
    Original addresses : 0x1bcd088, Value : 6
    Original addresses : 0x1bcd08c, Value : 4
    Original addresses : 0x1bcd090, Value : 4
    Original addresses : 0x1bcd094, Value : 6
    Original addresses : 0x1bcd098, Value : 2
    Original addresses : 0x1bcd09c, Value : 1
    Original addresses : 0x1bcd0a0, Value : 1
    
    
    
    
    
    
    
    
    (0x1bcd080, *r)2
    (0x1bcd084, *r)1
    (0x1bcd088, *r)6
    (0x1bcd08c, *r)4
    Somehow, the values at the address get swapped even if r and w don't reflect that. What's going on here?

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Basically, lines 74 though 84 of the output are where I'm confused. I just printed the addresses and the values of them and they were both 1 in the block above but now suddenly in the original vector, the value is changed. What's up?

  3. #3
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    One issue is that you're printing the address of w and k[w] after w is conditionally post incremented. As long as ...insert() is true, then r and w are both incremented and nothing in the vector changes with (*w++) = *r. The first time that ...insert() is false, w is not incremented, but also there's no copy operation. It's not until the next time that ...insert() is true that anything in the vector is changed, because at that point, w is less than r when (*w++) = *r is done.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    It's easier to follow like this:
    Code:
    // g++ -std=c++11 -Wall -Wextra unique.cpp
    
    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <set>
    using std::cout;
    
    int main(void)
    {
        std::vector<int> k = {6, 1, 6, 2, 6, 4, 2, 1, 3};
    
        cout << "original\n";
        for (size_t i = 0; i < k.size(); i++)
            cout << k[i] << ' ';
        cout << "\n\n";
    
        std::vector<int>::iterator r, w;
        std::set<int> set;
    
        for (r = k.begin(), w = r; r != k.end(); ++r)
        { 
            if (set.insert(*r).second)
                *(w++) = *r;
    
            cout << std::setw(2 * (r - k.begin() + 1)) << "r\n";
            cout << std::setw(2 * (w - k.begin() + 1)) << "w\n";
    
            for (size_t i = 0; i < k.size(); i++)
                cout << k[i] << ' ';
            cout << "\n\n";
        }
     
        k.erase(w, k.end());
    
        cout << "final\n";
        for (r = k.begin(); r != k.end(); ++r)
            cout << *r << ' ';
        cout << "\n";
    
        return 0;
    }
    
    /* Output:
    
    original
    6 1 6 2 6 4 2 1 3
    
    r
      w
    6 1 6 2 6 4 2 1 3
    
      r
        w
    6 1 6 2 6 4 2 1 3
    
        r
        w
    6 1 6 2 6 4 2 1 3
    
          r
          w
    6 1 2 2 6 4 2 1 3
    
            r
          w
    6 1 2 2 6 4 2 1 3
    
              r
            w
    6 1 2 4 6 4 2 1 3
    
                r
            w
    6 1 2 4 6 4 2 1 3
    
                  r
            w
    6 1 2 4 6 4 2 1 3
    
                    r
              w
    6 1 2 4 3 4 2 1 3
    
    final
    6 1 2 4 3
    */
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I think what's confusing me the most is
    Code:
    *(w++) = *r;
    In the beginning, r and w are equal to each other, the iterator returned from k.begin() and that's fine. I use begin() all the time.

    But I just don't understand how dereferencing your iterator doesn't change the value of what you're pointing to.

    Like, if r = k.begin then *r = 6.

    So shouldn't writing *(w++) = *r be like saying, hey, that next element after r should be equal to whatever *r is equal to now?

    Like, if you wanted to just increment the iterator, why use a dereference?

  6. #6
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    So basically, the first real line of output you show, I get. One points to 6 (that's r at the beginning) and then w points to the one right after it from w++.

    My bag is, *(w++) = 1 and *r = 6 so what they're saying is, *(w++) doesn't equal 1 but should be re-assigned to be 6. That's why I'm confused.

  7. #7
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Remember that this
    Code:
        *(w++) = *r;
    is equivalent to this
    Code:
        *w = *r;
        ++w;
    So the dereference and the increment are actually unconnected.

    BTW, a run with your original data looks like this:
    Code:
    original
    2 1 6 1 4 6 2 1 1
    
    r
      w
    2 1 6 1 4 6 2 1 1
    
      r
        w
    2 1 6 1 4 6 2 1 1
    
        r
          w
    2 1 6 1 4 6 2 1 1
    
          r
          w
    2 1 6 1 4 6 2 1 1
    
            r
            w
    2 1 6 4 4 6 2 1 1
    
              r
            w
    2 1 6 4 4 6 2 1 1
    
                r
            w
    2 1 6 4 4 6 2 1 1
    
                  r
            w
    2 1 6 4 4 6 2 1 1
    
                    r
            w
    2 1 6 4 4 6 2 1 1
    
    final
    2 1 6 4
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  8. #8
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Actually in my case, I can't remember that because I was never taught or shown that at the beginning.

    I literally just figured it out myself because I tried (++w) instead of (w++) and then it worked exactly like I thought then I pieced it together and you're 100% correct.

    Omg, I was having such a nerd fit over this and now the solution is so simple!

    Thank you so much for all your help, everyone!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can somebody explain this?
    By clmoore3 in forum C Programming
    Replies: 4
    Last Post: 03-21-2013, 11:41 AM
  2. could someone explain this for me?
    By qubit67 in forum C Programming
    Replies: 3
    Last Post: 04-05-2007, 01:39 AM
  3. Explain Me Please
    By abyu in forum C++ Programming
    Replies: 3
    Last Post: 11-07-2006, 06:29 AM
  4. Please explain?
    By neo_phyte in forum C Programming
    Replies: 3
    Last Post: 08-25-2006, 05:23 AM
  5. can anyone explain this?
    By anntenna333 in forum C Programming
    Replies: 6
    Last Post: 04-26-2006, 09:38 AM