Thread: vector constructor

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    596

    vector constructor

    Suppose I have one vector as follows:
    Code:
      vector<int> v1;
        for(int i = 0; i < 10; ++i) {
          v1.push_back(i+1);
        vector<int>::iterator next;
        }
    and I want to make a new vector containing, say, the first 5 elements of v1. Why is it OK to do
    Code:
      vector<int> v2(&v1[0], &v1[5]);
      
      for(next = v2.begin() ; next != v2.end(); ++next ) {
        cout << *next << " ";
      }
      cout << "\n";
    and OK to do
    Code:
      next = v1.begin();
      vector<int> v2(next, next+5);
    but not OK to do
    Code:
      vector<int> v2(v1.begin(), &v1[5]);

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well the short answer is that v1.begin() and &v1[5] aren't the same type (the first being std::vector<int>::iterator, the second being int*). I personally would be very surprised if there was any way that v1.begin()+5 == &v1[5] could even be true. (That doesn't mean it probably doesn't happen, of course.)

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    The compiler won't even let me make that kind of comparison. I tried
    Code:
      cout << (v1.begin() == &v1[0]) << endl;
    and was rewarded with
    Code:
    testv.cc: In function `int main()':
    testv.cc:47: error: no match for 'operator==' in 'std::vector<_Tp,
       _Alloc>::begin() [with _Tp = int, _Alloc = std::allocator<int>]() ==
       +(&v1)->std::vector<_Tp, _Alloc>::operator[] [with _Tp = int, _Alloc =
       std::allocator<int>](0)'
    I guess the real point of my question is, since that constructor wants iterators, why does it let me get away with
    Code:
      vector<int> v2(&v1[0], &v1[5]);  // the compiler allows this

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Because the compiler wants iterators. It does not require std::vector<int>::iterators, just iterators -- and specifically, two iterators of the same type (which these are -- int* is an iterator).

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by R.Stiltskin View Post
    I guess the real point of my question is, since that constructor wants iterators, why does it let me get away with
    Code:
      vector<int> v2(&v1[0], &v1[5]);  // the compiler allows this
    Because a pointer IS an iterator, in the sense this constructor wants. &v1[0] is of type int *, which is a perfectly meaningful iterator type
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Because the signature of the constructor is as follows:

    Code:
    template <class Iter>
    vector(Iter from, Iter to)
    where Iter can be a suitable pointer, vector::iterator, list::iterator, my_random_sequence_generator::iterator etc.

    As you can see both arguments must be of the same type.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    I have looked through the standard for a related question, but I can't find it. So I'll add it here, as it is interesting for the OP as well...
    The OP uses v1.begin() + 5. How is this defined for iterators? As I understand it, it is not defined to be a constant time operation; it may be implemented as O(n). &v1[5], however, is defined to be constant time.
    I think any implementation will probably make the + operator for an iterator on a vector constant time, but can you actually assume it does?

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Operator + should be constant time. There are several kinds of iterators, and if they can't implement operator+ in constant time then it is not available at all.

    There is also a std::advance(iterator, how_much) function which is constant time (iterator += how_much) for random access iterators and linear for others (++iterator how_much times). In your own applications you can get the type of the iterator using std::iterator_traits<some_iterator>::iterator_cate gory which is specialized for pointers, so pointers are recognized as random_access iterators too.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Quote Originally Posted by anon View Post
    Because the signature of the constructor is as follows:

    Code:
    template <class Iter>
    vector(Iter from, Iter to)
    where Iter can be a suitable pointer, vector::iterator, list::iterator, my_random_sequence_generator::iterator etc.

    As you can see both arguments must be of the same type.
    Well, you can see that, but it wasn't immediately apparent to me (although, thinking about it now, it does make sense that that should be the case). I have to say I'm still not accustomed to consulting official iso standards on a regular basis. I was looking at this (from cppreference.com):
    Code:
     #include <vector>
        vector();
        vector( const vector& c );
        vector( size_type num, const TYPE& val = TYPE() );
        vector( input_iterator start, input_iterator end );
        ~vector();
    which doesn't seem to say that the two iterators must be of the same type. Now I see, in the iso standard (which you seem to be paraphrasing),
    Code:
    23.2.4.1 vector constructors, copy, and assignment
    
        vector(const Allocator& = Allocator());
        explicit vector(size_type n, const T& value = T(),
                               const Allocator& = Allocator());
        template <class InputIterator>
          vector(InputIterator first, InputIterator last,
                     const Allocator& = Allocator());
        vector(const vector<T,Allocator>& x);
    but that seems to be a pretty "clunky" source for frequent reference.
    Do you know of a convenient online reference that provides more details than cppreference.com?
    Last edited by R.Stiltskin; 12-09-2008 at 10:39 AM.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Do you know of a convenient online reference that provides more details than cppreference.com?

    It's not an online reference, but The C++ Standard Library: A Tutorial and Reference by Josuttis.

    You can also go to the sites of actual library implementations. The two I usually check are from dinkumware and SGI:

    http://www.dinkumware.com/manuals/default.aspx
    http://www.sgi.com/tech/stl/table_of_contents.html

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    The MSDN provides a ton of detail and examples.
    Unfortunately they aren't always accurate and sometimes mix in MS specific crap.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  12. #12
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Quote Originally Posted by cpjust View Post
    The MSDN provides a ton of detail and examples.
    Unfortunately they aren't always accurate and sometimes mix in MS specific crap.
    That's a heckuva recommendation!

Popular pages Recent additions subscribe to a feed