スマートポインタ——《C++Primer》Chapter 14


最近C++の勉強を始め、読み直してずっと読んでいないC++Primer.
本のコードや練習問題を叩いたり、拡張したりします.
ここでいくつかの総括と記録をして、本を読むノートでしょう.
###############################################################
概要:
Chapter 14は主にいくつかのオペレータのリロードの問題について話した.
IOリロードはなぜ友元関数を使うのですか?前++と後++の重荷重はどのように区別しますか?
*、->をリロードするときはconstと非constの2つのバージョンを実装したほうがいいです.
->重荷、いったい何をコンパイルしたのか、O(∩∩)O~
この2,3日スマートポインタを見て、手がかゆくて簡単なバージョンを実現しました:referenceカウントに基づいて実現しました
カウンタを元のヌードポインタにバインドし、スマートポインタにカプセル化することです.
このようなメリットは、newが出てきたものは、いつdelete、スマートポインタに関心を持つ必要はありません.
すべてを手伝ってあげることができます.(相互参照はしばらく考慮しない)
汎用性を持つためにtemplateと書いてみましたが、templateのコードを使っているかどうか分かりません.
必ずすべてヘッダーファイルに入れますか?指図を求める.
カウンタ:
template <typename T> class SmartPtr;

class SPtrCounter
{
	template <typename T> friend class SmartPtr;

	int counter; // reference counter

	SPtrCounter(int n = 1): counter(n) {}
	void incRef() { counter++; }
	void decRef() { counter--; }
	int refNum() { return counter; }
};

このクラスは外部の人に見られたくないのでprivateにしてSmartPtrを友元クラスにします.
P.S.友元类を宣言する时templateとfriendの顺番、私は来て反対して、C++はよく知らないで、ほほほ.
スマートポインタ:
1.コピーコンストラクタを再ロードし、参照数を増やす
SmartPtr(const SmartPtr<T> &origin): 
	objPtr(origin.objPtr), counter(origin.counter)
{
	counter->incRef();
	print("Copy Constructor");
}

2.構造関数を再ロードし、参照カウントを減らして0かどうかを判断しdelete
~SmartPtr()
{
	counter->decRef();
	print("Deconstructor");
	if (counter->refNum() == 0)
	{
		delete counter;
		delete objPtr;
		std::cout << "Released memory: " << objPtr << std::endl;
	}
}

3.重荷付与操作、処理カウント、P.S.処理手順が適切であれば、自身付与問題であるか否かを判断する必要はない、ほほほ.
template<typename T>
SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T> &rhs)
{
	print("Before assignment");
	rhs.counter->incRef();
	counter->decRef();
	if (counter->refNum() == 0)
	{
		delete counter;
		delete objPtr;
		std::cout << "Released memory: " << objPtr << std::endl;
	}

	objPtr = rhs.objPtr;
	counter = rhs.counter;
	print("After assignment");
}

4.スマートポインタを1つのポインタのように表現するには、次のオペレータを再ロードします.
T& operator*();
T* operator->();
const T& operator*() const;
const T* operator->() const;

テスト:
#include <iostream>
#include <string>

#include "SmartPointer.h"

using namespace std;

class Person
{
public:
	static SmartPtr<Person> getInstance(const string &name);

	Person(const string name=""): name(name) 
	{
		cout << name << "'s constructor is invoked" << endl;
	}

	void print()
	{
		cout << "My name is " << name << endl;
	}

	~Person()
	{
		cout << name << "'s deconstructor is invoked" << endl;
	}

private:
	string name;
};

SmartPtr<Person> Person::getInstance(const string &name)
{
	return SmartPtr<Person>(new Person(name));
}

int main()
{
	SmartPtr<Person> sp1 = Person::getInstance("Jack");
	SmartPtr<Person> sp2 = Person::getInstance("Tom");
	
	cout << "***Test auto releasing***" << endl;
	{
		SmartPtr<Person> newSptr = sp1;
		(*newSptr).print();
	}
	sp1->print();

	cout << "***Test assignment***" << endl;
	sp1 = sp2;
	sp1->print();
	return 0;
}

出力結果:
Jack's constructor is invoked
Constructor: 0x8aae020, refNum: 1
Tom's constructor is invoked
Constructor: 0x8aae078, refNum: 1
***Test auto releasing***
Copy Constructor: 0x8aae020, refNum: 2
My name is Jack
Deconstructor: 0x8aae020, refNum: 1
My name is Jack
***Test assignment***
Before assignment: 0x8aae020, refNum: 1
Jack's deconstructor is invoked
Released memory: 0x8aae020
After assignment: 0x8aae078, refNum: 2
My name is Tom
Deconstructor: 0x8aae078, refNum: 1
Deconstructor: 0x8aae078, refNum: 0
Tom's deconstructor is invoked
Released memory: 0x8aae078

ソース:
https://github.com/niaokedaoren/CPP_Primer/tree/master/Chapter14/SmartPointer