C++を勉強中なのですが、スマートポインタについて質問があります。
自作クラス(Node)のポインタをvector配列に入れてるのですが、メモリ管理が大変になるので、自作クラスをスマートポインタで管理しようとしました。
以下に実装したスマートポインタを示します。
#ifndef TestSmart_ptr_smart_ptr_h
#define TestSmart_ptr_smart_ptr_h
#define SAFE_DELETE(p) if(p){delete p;p=0;}
template <typename T>
class smart_ptr{
public:
explicit smart_ptr(T* src = NULL); //コンストラクタ
smart_ptr(const smart_ptr<T> &src);//コピーコンストラクタ
smart_ptr<T>& operator =(const smart_ptr<T> &src);
virtual ~smart_ptr();//デストラクタ
T& operator*(){ return *m_pPtr; }//*関数
T* operator->(){ return m_pPtr; } //->関数
void AddRef(){ (*m_pRefCnt)++; }
void Release();
private:
T* m_pPtr; //T型へのポインタ
int *m_pRefCnt; //参照カウンタ変数
};
//--------------------------------------------------------------------------------------------
//@@@@@@@@@@@@@@@@@@@コンストラクタ@@@@@@@@@@@@@@@@@@@@@
//--------------------------------------------------------------------------------------------
template<typename T> smart_ptr<T>::smart_ptr(T* src)
{
//Tへのポインタを保持
m_pPtr = src;
//ポインタの先に実体が存在する場合
if (m_pPtr) {
//参照カウンタを作成
m_pRefCnt = new int; //参照カウンタへのポインタを作成
*m_pRefCnt = 0; //参照カウンタへのポインタを0にします
AddRef(); //参照カウンタを1にします
}
}
//コピーコンストラクタ
template <typename T> smart_ptr<T>::smart_ptr(const smart_ptr<T> &src)
{
printf("コピーコンストラクタが呼ばれました\n");
//ポインタコピー
m_pRefCnt = src.m_pRefCnt;
m_pPtr = src.m_pPtr;
//コピー先はコピー元からも参照されているので、参照カウンタを1増加させる
AddRef();
}
//--------------------------------------------------------------------------------------------
//@@@@@@@@@@@@@@@@@@@デストラクタ@@@@@@@@@@@@@@@@@@@@@
//--------------------------------------------------------------------------------------------
template <typename T> smart_ptr<T>::~smart_ptr<T>()
{
Release();
}
//--------------------------------------------------------------------------------------------
//@@@@@@@@@@@@@@@@@@@演算子のオーバーロード@@@@@@@@@@@@@@@@@@@@@
//--------------------------------------------------------------------------------------------
template <typename T> smart_ptr<T>& smart_ptr<T>::operator=(const smart_ptr<T> &src)
{
if (*src.m_pRefCnt == 0) {
Release();
}else{
//自分自身へのコピーは意味がないので行わない
//例
//smart_ptr<Ship> pShip(new Ship(10));
//pShip = pShip; <-意味がない
if (m_pPtr == src.m_pPtr) return (*this);
//自分の参照カウンタを1つ減少
Release();
//ポインタコピー
m_pRefCnt = src.m_pRefCnt;
m_pPtr = src.m_pPtr;
AddRef();
}
}
template <typename T> void smart_ptr<T>::Release()
{
if (m_pRefCnt) {
(*m_pRefCnt)--;
if ( (*m_pRefCnt) >0 ) return;
//もし参照カウンタが0だったら、ポインタ先の実体と参照カウンタへのポインタを削除
SAFE_DELETE(m_pPtr);
SAFE_DELETE(m_pRefCnt);
}
}
#endif
shared_ptrを使いたかったのですが、使用しているゲームエンジンがc++11をサポートしてないので、自作でスマートポインタ(smart_ptr)を実装しました。
smart_ptrを用いてNodeクラスを管理してる様子を以下に簡単なサンプルコードで示してます。
#include <iostream>
#include <vector>
#include "smart_ptr.h"
class Ship{
public:
Ship(int var)
:x(var)
{}
~Ship(){}
int getVar(){ return x; }
bool operator == (Ship ship){ return this->getVar() == ship.getVar(); }
private:
int x;
};
//変数
typedef smart_ptr<Ship> shipPtr;
typedef std::vector<smart_ptr<Ship>> ships;
//関数オブジェクト
class Find{
public:
shipPtr operator()(ships &list ,shipPtr pNode);
};
shipPtr Find::operator()(ships &list, shipPtr pNode)
{
int i=0;
for (ships::iterator it = list.begin(); it != list.end(); ++it) {
i++;
shipPtr pNodeItem = (*it);
if (*pNodeItem == *pNode) {
printf("%d 回目で見つかりました\n",i);
return pNodeItem;
}
}
return NULL; //①ここについてです。
}
int main(int argc, const char * argv[])
{
ships list;
shipPtr pShip(new Ship(10));
list.push_back(pShip);
shipPtr pShip2 = pShip;
list.push_back(pShip2);
shipPtr pShip3(new Ship(30));
list.push_back(pShip3);
shipPtr pShip10(NULL);
Find find;
//関数オブジェクトを呼んでいます
pShip10 = find(list,pShip2);
return 0;
}
No viable conversion from long to shipPtr
とコンパイラに言われてしまいました。
NULLを返して、pShip10で受け取るので、スマートポインタ中の代入演算子のオーバーロードのところをいじれば良いのかなと思ったのですが、どのように変更を施せばよいのでしょうか?