1

Consider the below example :

#include <iostream>
#include <vector>

class S {
public:
  S() { puts("S()"); }
  S(int) { puts("S(int)"); }
  ~S() { puts("~S()"); }
  S(const S &) { puts("S(const S&)"); }
  S(S &&) { puts("S&&"); }
  const S &operator=(const S &s) {
    puts("=");
    return s;
  }
  S &operator=(S &&s) {
    puts("Move =");
    return s;
  }
};

int main() {
  std::vector<S> s;
  s.emplace_back();
  s.emplace_back(6);
}

O/p :

S()
S(int)
S(const S&)
~S()
~S()
~S()

When only one element is emplaced_back, the constructor/destructor pair are called exactly once. But when there are multiple emplace_back (like s.emplace_back(6);), the copy constructor is also called. Why is this behavior difference ? is there still a copy exists with emplace_back ?

Sitesh
  • 1,816
  • 1
  • 18
  • 25

2 Answers2

3

Take into account that std::vector sometimes enlarges it's allocated area (when you add to many elements) and must copy old values over to new positions. This cause the call of the copy constructor.

You can call reserve()

std::vector<S> s;
s.reserve(20);
s.emplace_back();
s.emplace_back(6);

to say the s vector has to reserve a larger memory area to avoid relocations of elements.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
max66
  • 65,235
  • 10
  • 71
  • 111
3

This is because reallocation happens as explained by @max66. As for why it is the copy constructor being called, it is because your move constructor is not noexcept.

Change to this:

S(S &&) noexcept { puts("S&&"); }

Then it's the move constructor being called.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
  • I am not seeing any difference in terms of construction with adding `noexcept` to move ctor (without `reserve`). Only the copy constructor is replaced with the move constructor. – Sitesh Mar 26 '18 at 17:39
  • 1
    @Sitesh nothrow_move_constructible is the requirement for calling move constructor in `std::vector` reallocation. – llllllllll Mar 26 '18 at 17:42