#include <iostream>
#include <string>

class X {
public:
	explicit X(const std::string& name)
		: name_ptr(new std::string(name)) {
		std::cout << "Construct X name= " << *name_ptr << '\n';
	}

	// non copyable
	X(const X& x) = delete;
	X& operator=(const X& x) = delete;

	void info() const {
		std::cout << "info() in X\n";
	}

	X(X&& x) {
		std::cout << "Move construct name = " << *(x.name_ptr) << '\n';
		name_ptr = x.name_ptr;
		x.name_ptr = nullptr;
	}
	X& operator=(X&& x) {
		std::cout << "Move operator= name = " << *(x.name_ptr) << '\n';
		if (name_ptr != nullptr) {
			delete name_ptr;
		}
		name_ptr = x.name_ptr;
		x.name_ptr = nullptr;
		return *this;
	}
	~X() {
		std::cout << "Destruct name= ";
		if (name_ptr != nullptr) {
			std::cout << *name_ptr;
		} else { 
			std::cout << "nullptr";
		}
		std::cout << '\n';
		// Nadmiarowe i edukacyjne
		if (name_ptr != nullptr) {
			delete name_ptr;
		}
	}
private:
	std::string * name_ptr;
};

void foo(X&& my_x) {
	std::cout << "In foo()\n";
	my_x.info();
}

int main() {
	auto x1 = X("DNA Myszy");	
	auto x2 = std::move(x1);

	foo(std::move(x2));
	std::cout << "After foo()\n";
}
