Sol W2

Expected Observations for the Tracer Assignment

Tracer in Standard Container

Observing the push_back Operations

At a glance, when checking the output of the four push_back operations there are more copies than expected. Especially, T1 is copied several (three in my case) times. These copies happen when adding elements to a vector that has reached the capacity of the array used to store the elements. When this happens a new (bigger) array is allocated and all elements are copied to this new array. The old array is then deallocated.

Below is an excerpt from the output to show this behavior. It is generated by the v.push_back(Tracer{"T2"}) statement.

Tracer created: T2           (1)
Tracer copied: T2 copy       (2)
Tracer copied: T1 copy copy  (3)
Tracer destroyed: T1 copy    (4)
Tracer destroyed: T2         (5)

Copying the vector

The result of copying the vector is straight-forward. Every element of the vector is copied again.

Tracer copied: T1 copy copy copy copy
Tracer copied: T2 copy copy copy
Tracer copied: T3 copy copy
Tracer copied: T4 copy copy

Copy-Assignment

The implementation of the copy-assignment operator is as follows:

Tracer & operator=(Tracer const & rhs) {
  name = rhs.name + " copy-assigned";
  std::cout << "Tracer copy-assigned: " << name << std::endl;
  return *this;
}

Move Operations

The copy-constructor and the copy-assignment operator are replaced by the following implementations of the move-constructor and the move-assignment operator:

Tracer(Tracer && other) :
  name { other.name + " moved from" } {
  other.name = "";
  std::cout << "Tracer moved: " << name << std::endl;
}

Tracer & operator=(Tracer && rhs) {
  std::swap(name, rhs.name);
  name += " moved from";
  std::cout << "Tracer move-assigned: " << name << std::endl;
  return *this;
}

#include <utility>
...
foo(std::move(inner));
...
std::vector<Tracer> v_copy { std::move(v) };
...
sink = std::move(source);

Vector Again

When adding Tracers to the vector the copy operations are just replaced by the corresponding move operations. But, there is a change when moving the vector to another vector! This operation does not have any effect on the contained Tracer objects at all! Because they are left in the same memory location no additional move operation happens.

Moving vs. Copying Large Objects

It takes some elements to observe a timing difference between copy and move operations. But even on fast computers when copying or moving 1GB of data the difference should be measurable. If you cannot see the difference at any size, check whether you have enabled some kind of optimization in your compiler that eliminates the operations you are trying to measure completely.

Last edited March 1, 2017