#include <iostream>
template<typename T>
class SharedPtr {
T* value;
int* ref_count;
public:
SharedPtr(T* value) : value(value) {
ref_count = new int;
*ref_count = 1;
}
SharedPtr(const SharedPtr& other) {
value = other.value;
ref_count = other.ref_count;
(*ref_count)++;
}
SharedPtr(SharedPtr&& other) {
value = other.value;
ref_count = other.ref_count;
other.ref_count = nullptr;
}
~SharedPtr() {
if (ref_count == nullptr) {
return;
}
if (*ref_count == 1) {
delete value;
delete ref_count;
} else {
(*ref_count)--;
}
}
T& operator *() const {
return *value;
}
T* operator ->() const {
return value;
}
};
struct Pituh {
Pituh() {
std::cout << "Koko()" << std::endl;
}
~Pituh() {
std::cout << "~Koko()" << std::endl;
}
void kukareku() {
std::cout << "kukareku" << std::endl;
}
};
void kukareknut1(SharedPtr<Pituh> pet) {
pet->kukareku();
}
void kukareknut2(SharedPtr<Pituh> pet) {
(*pet).kukareku();
}
int main() {
{
SharedPtr<Pituh>(new Pituh);
}
std::cout << std::endl;
{
SharedPtr<Pituh> x(new Pituh);
auto y = x;
kukareknut1(y);
kukareknut2(std::move(y));
}
std::cout << std::endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KY2xhc3MgU2hhcmVkUHRyIHsKICAgIFQqIHZhbHVlOwogICAgaW50KiByZWZfY291bnQ7CgpwdWJsaWM6CiAgICBTaGFyZWRQdHIoVCogdmFsdWUpIDogdmFsdWUodmFsdWUpIHsKICAgICAgICByZWZfY291bnQgPSBuZXcgaW50OwogICAgICAgICpyZWZfY291bnQgPSAxOwogICAgfQoKICAgIFNoYXJlZFB0cihjb25zdCBTaGFyZWRQdHImIG90aGVyKSB7CiAgICAgICAgdmFsdWUgPSBvdGhlci52YWx1ZTsKICAgICAgICByZWZfY291bnQgPSBvdGhlci5yZWZfY291bnQ7CiAgICAgICAgKCpyZWZfY291bnQpKys7CiAgICB9CgogICAgU2hhcmVkUHRyKFNoYXJlZFB0ciYmIG90aGVyKSB7CiAgICAgICAgdmFsdWUgPSBvdGhlci52YWx1ZTsKICAgICAgICByZWZfY291bnQgPSBvdGhlci5yZWZfY291bnQ7CiAgICAgICAgb3RoZXIucmVmX2NvdW50ID0gbnVsbHB0cjsKICAgIH0KCiAgICB+U2hhcmVkUHRyKCkgewogICAgICAgIGlmIChyZWZfY291bnQgPT0gbnVsbHB0cikgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoKnJlZl9jb3VudCA9PSAxKSB7CiAgICAgICAgICAgIGRlbGV0ZSB2YWx1ZTsKICAgICAgICAgICAgZGVsZXRlIHJlZl9jb3VudDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAoKnJlZl9jb3VudCktLTsKICAgICAgICB9CiAgICB9CgogICAgVCYgb3BlcmF0b3IgKigpIGNvbnN0IHsKICAgICAgICByZXR1cm4gKnZhbHVlOwogICAgfQoKICAgIFQqIG9wZXJhdG9yIC0+KCkgY29uc3QgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KfTsKCnN0cnVjdCBQaXR1aCB7CiAgICBQaXR1aCgpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIktva28oKSIgPDwgc3RkOjplbmRsOwogICAgfQogICAgflBpdHVoKCkgewogICAgICAgIHN0ZDo6Y291dCA8PCAifktva28oKSIgPDwgc3RkOjplbmRsOwogICAgfQogICAgdm9pZCBrdWthcmVrdSgpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgImt1a2FyZWt1IiA8PCBzdGQ6OmVuZGw7CiAgICB9Cn07Cgp2b2lkIGt1a2FyZWtudXQxKFNoYXJlZFB0cjxQaXR1aD4gcGV0KSB7CiAgICBwZXQtPmt1a2FyZWt1KCk7Cn0Kdm9pZCBrdWthcmVrbnV0MihTaGFyZWRQdHI8UGl0dWg+IHBldCkgewogICAgKCpwZXQpLmt1a2FyZWt1KCk7Cn0KCmludCBtYWluKCkgewogICAgewogICAgICAgIFNoYXJlZFB0cjxQaXR1aD4obmV3IFBpdHVoKTsKICAgIH0KICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7CgogICAgewogICAgICAgIFNoYXJlZFB0cjxQaXR1aD4geChuZXcgUGl0dWgpOwogICAgICAgIGF1dG8geSA9IHg7CiAgICAgICAga3VrYXJla251dDEoeSk7CiAgICAgICAga3VrYXJla251dDIoc3RkOjptb3ZlKHkpKTsKICAgIH0KICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7Cn0=