1

To my understanding, when a vector increases its capacity, it allocates a new memory, copy(move?) all contents to the new array, and then destroy the old one:

vector<int> v;
v.emplace_back(1);
v.emplace_back(2); cout<<&v[0]<<endl; // outputs 0x4b16d0
v.emplace_back(3); cout<<&v[0]<<endl; // outputs 0x4b16f0

         +-----+  
0x4b16d0 | 1 2 |  
         +-----+  

         +---------+  
0x4b16f0 | 1 2 3   |  
         +---------+  

In above example, how 1 and 2 move from 0x4b16d0 to 0x4b16f0?


Updated with user-defined class

struct foo {
    foo() {}
    foo(const foo &) { cout << "copy\n"; }
    foo(foo &&) noexcept { cout << "move\n"; }
};

int main() {
    vector<foo> v;
    cout<<"1st emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
    cout<<"2nd emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
}

$ g++ -std=c++11 -g a.cpp; ./a.exe
1st emplace_back()
 addr of 1st element: 0x6f16d1
2nd emplace_back()
move
 addr of 1st element: 0x6f16f1

My question is, even the move ctor is called, it still copies data from one place to another, is that right?

If so, does that mean it doesn't improve performance at all when vector increase its capacity using move semantics?

Deqing
  • 14,098
  • 15
  • 84
  • 131
  • It uses the method described in your question. It copies them. – Bill Lynch Aug 20 '15 at 03:30
  • A non-trivial class with a user-defined move-constructor + debugger + breakpoint + view call-stack will likely give you an idea how your implementation does this. Or is your question specifically about `int` ? – WhozCraig Aug 20 '15 at 03:31
  • @Deqing you realize both of those should be using `&v[0]`, right? – WhozCraig Aug 20 '15 at 04:04
  • Hint: output `v.capacity()` after each call to `v.emplace_back()`. Now, why do you suppose the address of the first element is changing? – paddy Aug 20 '15 at 04:16
  • You have one "move" and no "copy" in your output. About what copy are you talking? If a vector can move your objects it will move them, no copy will be there so it is definitely improves performance. – ixSci Aug 20 '15 at 04:19
  • BTW, first element has zero index, not 1. So in the first cout line you are touching the memory you have no right to. So it is a UB. – ixSci Aug 20 '15 at 04:20
  • Imagine your object holds something considerably more complex than nothing. Say, something expensive to copy, but cheap to move (like a `std::vector` holding a half-million elements). The copy would be hideous. The move would be simply transferring ownership of a `std::vector<>`'s housekeeping implementation from one object to another. – WhozCraig Aug 20 '15 at 04:30
  • 2
    Might want to keep in mind also: The vector will only move your object if the object has a no-throw move constructor. By default it will end up being declared this way (most likely). If the move constructor may throw then vectors will use the copy constructor instead. It's based on this standard utility: http://en.cppreference.com/w/cpp/utility/move_if_noexcept – Chris Beck Aug 20 '15 at 04:30

1 Answers1

2

Your vector is vector<int> . Moving an int is the same as copying it, so there is no "performance gain" here.

If you had vector<std::string> then you would notice a difference; the large strings will be moved from the old memory location to the new memory location. This will be faster than copy-constructing new strings in the new location and destructing the old strings.

(As noted by Chris Beck , the objects are only moved if their move-constructor cannot throw, but I am confident that is the case for std::string).

I'm not sure what you are trying to test in your foo example since your foo does not actually contain any data.

M.M
  • 138,810
  • 21
  • 208
  • 365