shared_ptrの使い方を知りたかったからいろいろ試してみた (2)

前回shared_ptrの使い方を適当に勉強したので、早速使ってみるぞーと思って使ってみたら"あれ?これどうすんだ?"ってことがあったのでそれらの確認をします。

constは?

shared_ptrを引数で渡すにはとりあえずそのまま渡しても動きます

#include "stdafx.h"
#include <memory>
#include <iostream>

class Hoge {
public:
	Hoge(){}
	~Hoge(){
		std::cout << "Hogeのデストラクタだよ" << std::endl;
	}
	int number_;
};

void func(std::shared_ptr<Hoge> hoge) {
	if(hoge == nullptr) return;
	std::cout << hoge->number_ << " " << hoge.use_count() << std::endl;

}

int _tmain(int argc, _TCHAR* argv[])
{
	{
		std::shared_ptr<Hoge> hoge1(new Hoge);
		hoge1->number_ = 5;
		func(hoge1);
		
	}

	return 0;
}

ただ、これだと値渡しされるので関数func内ではuse_count()は2になります。

use_count()を増やす意味があるならこのままで良いですが基本的にはconst参照渡しでよいでしょう。

#include "stdafx.h"
#include <memory>
#include <iostream>

class Hoge {
public:
	Hoge(){}
	~Hoge(){
		std::cout << "Hogeのデストラクタだよ" << std::endl;
	}
	int number_;
};

void func(const std::shared_ptr<Hoge>& hoge) {
	if(hoge == nullptr) return;
	std::cout << hoge->number_ << " " << hoge.use_count() <<  std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	{
		std::shared_ptr<Hoge> hoge1(new Hoge);
		hoge1->number_ = 5;
		func(hoge1);
		
	}

	return 0;
}

これだと関数内でのuse_count()は1です。

ただし、ここでのconstはアドレスが変わらないって言う意味で、アドレスが指す先が変わらないというわけではないです。

つまり、ポインタで言うところのvoid func(Hoge * const hoge)的なことです。

#include "stdafx.h"
#include <memory>
#include <iostream>

class Hoge {
public:
	Hoge(){}
	~Hoge(){
		std::cout << "Hogeのデストラクタだよ" << std::endl;
	}
	int number_;
};

void func(const std::shared_ptr<Hoge>& hoge) {
	if(hoge == nullptr) return;
	hoge->number_ = 10;
	std::cout << hoge->number_ << " " << hoge.use_count() <<  std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	{
		std::shared_ptr<Hoge> hoge1(new Hoge);
		hoge1->number_ = 5;
		func(hoge1);
		std::cout << hoge1->number_ << std::endl; // 10が表示される
	}

	return 0;
}

そんならポインタで言うところのvoid func(const Hoge* hoge)はどうすんの?ってことになります。
⇒ void func(const shared_ptr hoge)でいけます

#include "stdafx.h"
#include <memory>
#include <iostream>

class Hoge {
public:
	Hoge(){}
	~Hoge(){
		std::cout << "Hogeのデストラクタだよ" << std::endl;
	}
	int number_;
};

void func(const std::shared_ptr<const Hoge>& hoge) {
	if(hoge == nullptr) return;
	//hoge->number_ = 10; // コンパイル時エラーになるよ
	std::cout << hoge->number_ << " " << hoge.use_count() <<  std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	{
		std::shared_ptr<Hoge> hoge1(new Hoge);
		hoge1->number_ = 5;
		func(hoge1);
		std::cout << hoge1->number_ << std::endl;
	}

	return 0;
}

恥ずかしながらなんでuse_count()が2になるのかがあんまり良く分かってません。

shared_ptrとshared_ptrが別の型だから型変換のための一時オブジェクトが関数に飛ぶ前に生じてその参照が関数に渡されるって理解でいいのでしょうか?

dynamic_castは?

dynamic_castはできるなら使いたくないですが、それはそれとして使い方を知っとくことはいいことだろうと。

shared_ptrの場合はdynamic_castの変わりにdynamic_pointer_castを用いるそうです。

#include "stdafx.h"
#include <memory>
#include <iostream>

class Hoge {
public:
	Hoge(){}
	virtual ~Hoge(){
		std::cout << "Hogeのデストラクタだよ" << std::endl;
	}
	int number_;
};

class DerivedHogeA : public Hoge {
public:
	DerivedHogeA(){}
	virtual ~DerivedHogeA(){}
};

class DerivedHogeB : public Hoge {
public:
	DerivedHogeB(){}
	virtual ~DerivedHogeB(){}
};

int _tmain(int argc, _TCHAR* argv[])
{
	{
		std::shared_ptr<Hoge> hoge1(new DerivedHogeA);

		if(std::dynamic_pointer_cast<DerivedHogeA>(hoge1) == nullptr)
			std::cout << "hoge1はDerivedHogeAじゃないよ" << std::endl;
		else
			std::cout << "hoge1はDerivedHogeAだよ" << std::endl;

		if(std::dynamic_pointer_cast<DerivedHogeB>(hoge1) == nullptr)
			std::cout << "hoge1はDerivedHogeBじゃないよ" << std::endl;
		else
			std::cout << "hoge1はDerivedHogeBだよ" << std::endl;

	}

	return 0;
}