doubling by copy

K

Klaus Ahrens

hi all,

is it legal to double the content of a vector c by

copy(c.begin(), c.end(), back_inserter(c));

when ensuring before

c.reserve(2*c.size());

???

best regards

k ahrens
 
V

Victor Bazarov

Klaus said:
is it legal to double the content of a vector c by

copy(c.begin(), c.end(), back_inserter(c));

when ensuring before

c.reserve(2*c.size());

???

I don't see any problem with it. If no reallocation happens (and
'reserve' should take care of that), all iterators stay valid, and
you're just copy-constructing elements after the previous end.
The only one thing I'd worry about is that the 'end' changes, so
there can be an implementation in which the object returned by
'c.end()' can keep changing when you push_back (moving target).

If you need to simply grow the vector by copying its contents at
the end, why not try

c.reserve(..
c.insert(c.end(), c.begin(), c.end());

it might be slightly faster.

V
 
D

Daniel T.

"Victor Bazarov said:
I don't see any problem with it. If no reallocation happens (and
'reserve' should take care of that), all iterators stay valid, and
you're just copy-constructing elements after the previous end.
The only one thing I'd worry about is that the 'end' changes, so
there can be an implementation in which the object returned by
'c.end()' can keep changing when you push_back (moving target).

How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?
 
J

joosteto

Daniel said:
How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?

Yes, if the copy() function is written properly. The following copy()
function never ends:

#include <vector>
#include <iostream>

using namespace std;

void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}
}

int main(){
vector<int> v;
v.push_back(1);
v.push_back(2);
copy(v,v.begin(), v.end());
}
 
R

red floyd

Yes, if the copy() function is written properly. The following copy()
function never ends:

#include <vector>
#include <iostream>

using namespace std;

void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}
}

However, according to 25.2.1, that can't happen, as the iterators are
passed by value, not by reference. The footprint for std::copy is as
follows:

template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
 
J

joosteto

Daniel said:
How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?

Yes, if the copy() function is written properly. The following copy()
function never ends: [..]
void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}

Oops, sorry, of course that doens't end. I thought that the iterator by
reference would change, but clearly it doesn't with the standard vector
class.

I guess if the c.end() in the original example were to return a
reference to an internal iterator, then a problem would occur.
 
V

Victor Bazarov

Daniel said:
How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?

Yes, if the copy() function is written properly. The following copy()
function never ends: [..]
void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}

Oops, sorry, of course that doens't end. I thought that the iterator
by reference would change, but clearly it doesn't with the standard
vector class.

I guess if the c.end() in the original example were to return a
reference to an internal iterator, then a problem would occur.

Even if 'copy' accepts an iterator by value, it's still possible for
that iterator to get the reference to the container, and perform some
kind of lookup based on the "real" (floating) end of the container when
'==' is used on it...

All those examples are of course beyond common sense, I guess.

V
 
D

Daniel T.

"Victor Bazarov said:
Daniel T. wrote:
How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?

Yes, if the copy() function is written properly. The following copy()
function never ends: [..]
void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}

Oops, sorry, of course that doens't end. I thought that the iterator
by reference would change, but clearly it doesn't with the standard
vector class.

I guess if the c.end() in the original example were to return a
reference to an internal iterator, then a problem would occur.

Even if 'copy' accepts an iterator by value, it's still possible for
that iterator to get the reference to the container, and perform some
kind of lookup based on the "real" (floating) end of the container when
'==' is used on it...

All those examples are of course beyond common sense, I guess.

Personally I would consider that an implementation error. Does the
standard say one way or the other?
 
A

Alan Johnson

Victor said:
Daniel T. wrote:
How could you have a moving target? c.end() is evaluated only once
before entering the copy function, isn't it?
Yes, if the copy() function is written properly. The following copy()
function never ends: [..]
void copy( vector<int> &v,
const vector<int>::iterator &b,
const vector<int>::iterator &e){
while(b!=e){
cout<<"size="<<v.size()<<endl;
v.push_back(*b);
}
Oops, sorry, of course that doens't end. I thought that the iterator
by reference would change, but clearly it doesn't with the standard
vector class.

I guess if the c.end() in the original example were to return a
reference to an internal iterator, then a problem would occur.

Even if 'copy' accepts an iterator by value, it's still possible for
that iterator to get the reference to the container, and perform some
kind of lookup based on the "real" (floating) end of the container when
'==' is used on it...

All those examples are of course beyond common sense, I guess.

V

While I can't find anything that prevents end() from being implemented
in such a way, I do believe that a version of copy() that couldn't
handle that would be non-conforming, since the complexity requirements
are "Exactly last - first assignments."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top