OSGスマートポインタosgについて::ref_ptrのいくつかのテスト

5901 ワード

OSGは長い間、プログラミングが下手で、読む本も少ないので、この新しいことに対する理解はいつもそんなに深くありません.近日1篇の博文《OSG知能の針の罠の総括》を見て、博文の中で多くの問題があることを発見して、特にここで自分のテストと感想を同じかすのあなたに分かち合います.
本論文のコードは『OSGインテリジェントポインタトラップ総括』の改編に従ってテストを行い,比較して見ることができる.
本文:
まず,スマートポインタの理解は,スマートポインタは本ノードが参照された回数,すなわち初期化後のカウントが1であり,自身が参照された回数を表す.OSg::Referencedから継承されたクラスのインスタンスは、参照カウントできます.また、スマートポインタオブジェクトとして宣言するかどうかにかかわらず、スマートポインタでも通常のポインタでも、参照後のカウントは増加します.(というのは、スマートポインタの理解に問題があると思うからです)
次に,出力ノードのnameは,そのノードが依然として有効であるか否かを判定するためである.
質問1:
次のコードは私が彼の最初の問題の解決方法に従って変更したものです.
#include 
#include 
#include 
#include 
#include 

#include 

// osg::ref_ptr rnode = NULL;
// osg::Group* root = NULL;

osg::Node *rnode = NULL;
osg::ref_ptr root = NULL;

// osg::Node *rnode = NULL;
// osg::Group *root = NULL;

void createNode(){
	rnode = osgDB::readNodeFile("lz.osg");
	rnode->setName("Hello");
	root = new osg::Group;
	root->addChild(rnode);
}
void GetNodeFromRoot(osg::Node ** node){

	for (int i = 0; i < root->getNumChildren(); ++i)
	{
		if (root->getChild(i)->getName().compare("Hello") == 0)
		{
			osg::Node * tmp = root->getChild(i);
			
			std::cout << rnode->getName() << tmp->getName() << rnode->referenceCount() << std::endl;
			//root->removeChild(tmp);
			//std::cout << rnode->getName() << tmp->getName() << rnode->referenceCount() << std::endl;
			*node = tmp;
			root->removeChild(tmp);
			std::cout << rnode->getName() << tmp->getName() << rnode->referenceCount() << std::endl;
		}
	}
}

int main()
{
	createNode();
	osg::Node * node = NULL;
	GetNodeFromRoot(&node);

	osg::Group* group = new osg::Group;
	group->addChild(node);

	osgViewer::Viewer viewer;
	viewer.setSceneData(group);

	return viewer.run();
}

彼の意味では、これは大丈夫だと思います.まず引用して、tmpを削除します.しかし、実際には実行されていません.
コンソールの出力から見ると、
HelloHello1
0
1回目の出力には何の問題もありませんが、2回目は明らかに出力ノードの名前がありません.rnodeは普通のポインタなので、root->removeChild(tmp)を行うと思います.操作後、メモリが解放されたため、名前を出力できません.こうなった以上、シーンに加わると必ずエラーが発生します.
解決方法:
rnodeをスマートポインタオブジェクトとして定義します.すなわち、
osg::ref_ptr<:node> rnode = NULL;
運転は問題ないでしょう.コンソールの出力は次のとおりです.
HelloHello2
HelloHello1
解釈:最初の出力カウントは2で、初期化後のrnode自体のカウントが1であるため、rootに加えた後、カウントに1を加え、2である.root->removeChild(tmp);カウントは1を減らして、1になります.
質問2:
int main()
{
	osg::ref_ptr node = osgDB::readNodeFile("glider.osg");
	//osg::Node * node = osgDB::readNodeFile("glider.osg");
	node->setName("glider");
	std::cout << node->getName() << node->referenceCount() << std::endl;

	{
		osg::ref_ptr root = new	osg::Group;
		root->addChild(node);
		std::cout << node->getName() << node->referenceCount() << std::endl;
	}
	// osg::Node *, node 。
	std::cout << node->getName() << node->referenceCount() << std::endl;

	{
		osg::ref_ptr root = new	osg::Group;
		root->addChild(node);
		osg::ref_ptr root2 = new	osg::Group;
		root2->addChild(node);
		osg::ref_ptr root3 = new	osg::Group;
		root3->addChild(node);
		std::cout << node->getName() << node->referenceCount() << std::endl;
		root->removeChild(node);
		std::cout << node->getName() << node->referenceCount() << std::endl;
	}
	std::cout << node->getName() << node->referenceCount() << std::endl;

	{
		osg::Group* root = new	osg::Group;
		root->addChild(node);
		//root->addChild(node);
		osg::Group* root2 = new	osg::Group;
		root2->setName("root2");
		root2->addChild(node);
		std::cout << node->getName() << node->referenceCount() << std::endl;

		//error ~Group() Protected Member Functions
		//delete root;
	}
	std::cout << node->getName() << node->referenceCount() << std::endl;
	osg::ref_ptr root = new	osg::Group;
	root->addChild(node);
	std::cout << node->getName() << node->referenceCount() << std::endl;
	return 0;
}

実行コード、エラー、コンソール出力:
glider0
glider1
0
解釈:nodeの作成が完了した後、ポインタのみが定義されていないため、カウントは0(実はこのカウントは何の意味もないので、すぐに説明します)、最初のセグメントにルートノードを加えた後、カウントに1を加え、最初のセグメントが終了すると、ルートノードが分析され、nodeが分析されるため、カウントはここで0になります.(2回目のカウントはいずれも0ですが本質的には違い、2回目の出力ではnodeのメモリはnodeに属していないので、さっきそのカウント0には何の意味もないと言っていました)、デバッグしてみると、3回目の出力は実際にエラーが発生して名前を算出できなかったことがわかります
解決策:nodeをスマートポインタとして定義します.すなわち、次のようにします.
osg::ref_ptr<:node> node = osgDB::readNodeFile("glider.osg");
実行コード、通過、出力:
glider 1----->イニシャルカウント1
glider 2----->親ノードを追加し、カウント+1
glider 1----->最初のフラグメントが終了すると、親ノードが解析され、カウント-1
glider 4---->親ノードを2回追加し、カウント+2
glider 3----->は1回削除され、カウント-1
glider 1----->親ノードroot 2,root 3が析出し,カウント-2
glider 3---->カウント+2
glider 3----->1じゃない!!!では、新しい問題が来ました.
glider4
説明すると、フラグメント2とフラグメント3を比較すると、親ノードがスマートポインタオブジェクトなのか通常のポインタなのか、フラグメント3がメモリをスタックに割り当て、手動で解放しなければならないのかが最大の違いであることがわかります.一方、フラグメント2で定義されたスマートポインタオブジェクトは通常のオブジェクトであり、スタックに割り当てられ、モジュールが終了すると自動的にプロファイルされ、彼のプロファイルはサブノードカウントを1減少させ、すなわちnodeカウントを減少させる.解決方法:~Groupはprotectedタイプなので、手動で呼び出すことはできません.ここではルートノードの下に追加してremoveを解放します.
 osg::Group* rroot = new osg::Group;
 {
  osg::Group* root = new osg::Group;
  root->addChild(node);
  //root->addChild(node);
  osg::Group* root2 = new osg::Group;
  root2->setName("root2");
  root2->addChild(node);
  std::cout << node->getName() << node->referenceCount() << std::endl;
  //error ~Group() Protected Member Functions
  //delete root;
  rroot->addChild(root);
  rroot->addChild(root2);
 }
 rroot->removeChild(0, rroot->getNumChildren());
今から出力しても大丈夫でしょう.
未完.