-1

In my hand-write vector I needed to implement insert function, so I did it like this:

void insert(size_t index, const T& x) { 
    std::copy(begin() + index, end() - 1, begin() + index + 1);
    new(storage_ + index) T(x); // "storage_" is my vector's inner array
}

And this works absolutely correct on test like this:

myvector<int> v;
for (int i = 0; i < 10; i++)
    v.push_back(i + 1);
v.insert(5, 0); // insert(size_t position, const T& element)

This outputs:

1 2 3 4 5 0 6 7 8 9 10

(this means insert worked fine)

But I absolutely don't understand why this code works the way it is because on cplusplus.com (link) I found that std::copy works like this:

template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
    while (first!=last) {
        *result = *first;
        ++result; ++first;
    }
return result;
}

But doesn't it mean, that if I call

std::copy(begin() + index, end() - 1, begin() + index + 1);

It will replace 7 with 6 when it executes *result = *first; and after ++result; ++first; it will replace 8 with 6 and so on.

In myvector iterators are defined like this:

typedef T* iterator;

and my begin/end is:

iterator begin() {
    return storage_ + 0;
}

iterator end() {
    return storage_ + size_;
}
PepeHands
  • 1,368
  • 5
  • 20
  • 36
  • 3
    If the OutputIterator is within the input range of `std::copy`, you invoke Undefined Behaviour. It is possible the effects you see are due to some optimization of `std::copy` in your implementation. – dyp May 28 '15 at 21:30
  • @dyp yeah, seems like this is the problem. Thanks! – PepeHands May 28 '15 at 21:34
  • Try `myvector` and your code will not behave as expected. As dyp says, using `myvector` probably results in `memmove` being called, which can handle overlapping ranges. – Praetorian May 28 '15 at 21:41
  • @Praetorian Why would `std::copy` call `memmove` instead of `memcpy`? – dyp May 28 '15 at 21:44
  • @dyp It's a guess, since `memcpy` isn't required to handle overlapping ranges correctly, and the OP's code is behaving as expected. Also, I have a vague recollection of hearing STL claim their `memmove` implementation is more efficient, or some such reason, because of which they delegate to it instead of `memcpy`, from `std::copy`. – Praetorian May 28 '15 at 21:50
  • @Praetorian While gcc does funny things with an SSCCE of this, rextester's vc++ [can reproduce the behaviour with `memcpy`](http://rextester.com/JSNCK64039) – dyp May 28 '15 at 21:53
  • 1
    @dyp HansPassant [claims](https://stackoverflow.com/questions/4415910/memcpy-vs-memmove#comment4816655_4415910) MSVC implements a "safe" `memcpy`; judging from the question he's commenting on, that means they handle overlapping ranges. I just took at peek at the VS2015 `` header, and their `std::copy` implementation does delegate to `memmove`. – Praetorian May 28 '15 at 22:09

1 Answers1

4

What you're doing there does not conform to the requirements of std::copy, which include that result NOT be within the range [begin,end). So anything's possible; you've broken the rules.

Anything is possible, that is... including it working correctly. It sounds like your particular standard library implementation has decided to be merciful, by noticing that you're violating the requirement and instead delegating to std::copy_backward. It's allowed to do this because one possible type of undefined behavior is "stuff still works".

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • Or possibly by just doing a backwards copy unconditionally: it's unlikely for an stdlib implementation to actually check whether the caller has violated this precondition because performance-wise it would penalize callers that do not violate it. – Andy Prowl May 28 '15 at 21:34
  • 2
    @AndyProwl The standard actually does require that elements be copied in forward order. Of course, if the elements were POD, it could do it backward anyway under the as-if rule. – Sneftel May 28 '15 at 21:42
  • @Sneftel: Ah, you're right. My bad, sorry, I should have known this :$ – Andy Prowl May 28 '15 at 21:47
  • @AndyProwl Well, I should've as well, but I still had to look it up to find out. ;-) – Sneftel May 28 '15 at 21:48