go to start Ex W2
|home |print view |recent changes |changed March 4, 2016 |
|You are <- set your identity!

Sections: Tracer Again | Tracer in Standard Container | Copy Assignment | Move Construction/Assignment | Vector Again | Moving vs. Copying Large Objects |

Tracer Again ^

From CPlusPlus you might already be familiar with the tracer class as used in the extra exercises. Today it's not extra anymore.

#include <iostream>
#include <string>

struct Tracer {
	explicit Tracer(std::string name = "") :  name { name } {
		std::cout << "Tracer created: " << name << std::endl;
	~Tracer() {
		std::cout << "Tracer destroyed: " << name << std::endl;
	Tracer(Tracer const& other) : name { other.name + " copy" } {
		std::cout << "Tracer copied: " << name << std::endl;
	void show() const {
		std::cout << "Tracer: " << name << std::endl;
	std::string name;

void foo(Tracer t) {
	Tracer trace("foo");

Tracer bar(Tracer const &t) {
	Tracer trace("bar");
	return trace;

int main() {
	Tracer m { "main" };
		Tracer inner { "inner" };
		auto trace = bar(inner);
	foo(Tracer { "temp" });

Tracer in Standard Container ^

Observe the behavior of the Tracer type when used in an std::vector.

  std::vector<Tracer> v{};

  std::vector<Tracer> v_copy{v};

Copy Assignment ^

Your Tracer type does not provide an assignment operator. Add one which adds with " copy-assigned" to the name, similar to the implemented constructors..

int main() {
  std::cout << "\t\t--- creating sink and source ----" << std::endl;
  Tracer sink {"sink"}, source {"source"};

  std::cout << "\t\t--- assigning source to sink ----" << std::endl;
  sink = source;

  std::cout << "\t\t--- showing sink ----" << std::endl;

  std::cout << "\t\t--- showing source ----" << std::endl;

  std::cout << "\t\t--- end of main ----" << std::endl;

Move Construction/Assignment ^

Replace the copy constructor and copy-assignment operator of the tracer class with a move constructor and a move-assignment operator. Within the move constructor change the parameter object's name to name+"moved from" and define the name of the moved-to object to be the other's original name.

What about the state of source after the move assignment?

As you have a moveable type what happens if you just call std::move on a tracer object? What is the output of the call below? Why?

int main() {
  std::cout << "\t\t--- std::move(m) ----" << std::endl;
  std::cout << "\t\t--- end of main ----" << std::endl;

Vector Again ^

Now as your Tracer is movable:

Moving vs. Copying Large Objects ^

Large objects can benefit from move operations. An std::vector, for example, allocates memory on the heap for storing its values. Copying a vector requires additional heap space and copies all values to this new memory location. Moving a vector just needs to move the pointers, which access this memory, to the move-constructed/assigned vector.

Try to measure the difference in allocating, copying and moving a large std::vector.

You can use std::chrono to measure the operations.

  auto start = std::chrono::system_clock::now();
  //allocate large vector
  std::chrono::duration<double> delta = std::chrono::system_clock::now() - start;
  std::cout << "creating the container took: " << delta.count() << "s time\n";

What size of vector is large enough to observe the behavior?

|home |print view |recent changes |changed March 4, 2016 |
|You are <- set your identity!

Ex W2
go to start