C++ での Singleton クラスの実装
「デザインパターン」では、シングルトンはリターンポインタとして記述されています:
class Singleton{ public: static Singleton* Instance(); protected: Singleton(); private: static Singleton* _instance; };
対応する実装 cpp ファイルは:
Singleton* Singleton::_instance; Singleton* Singleton::Instance(){ if( _instance == 0){ _instance = new Singleton; }; return _instance; }
コンストラクタを保護されたものとして設計する目的は、クラス外での新規作成を防ぐためです。 private を考慮すると、このクラスを継承できる場合は、コンストラクターを protected として設計し、仮想デストラクターを追加する必要があります。他の人が Singleton オブジェクトをコピーできないようにするには:
Singleton* pSingleton = Singleton::Instance(); Singleton s1 = *pSingleton; Singleton s2 = *pSingleton; 需要将拷贝构造(copy constructor)函数变成 private。
しかし、ここでの問題は、Singleton オブジェクトをいつ削除するかということです。 C++ の基本原則に従って、オブジェクトは作成された場所では必ず破棄されます。Singleton オブジェクトを削除するための destroy メソッドも必要です。消し忘れるとさらに面倒です。インスタンス関数には、複数のスレッドによる同時アクセスによるロックの問題もあります。インスタンス関数の最初と最後にロックとロック解除を配置すると、関数全体のパフォーマンスが大幅に低下します。これは良い設計ではありません。
Singleton オブジェクトの削除忘れによって引き起こされるメモリ リークの問題を回避できる小さな変更があります。つまり、 std:auto_ptr を使用して Singleton オブジェクトを含め、クラスの静的メンバー auto_ptr オブジェクトを定義し、静的 auto_ptr 変数が破棄されたときに Singleton オブジェクトを自動的に削除します。ユーザーがシングルトン オブジェクトを削除できないようにするには、デストラクターをパブリックからプロテクトに変更する必要があります。以下は、ヘッダー ファイル SingletonAutoPtr.h です:
#include <memory> using namespace std; class CSingletonAutoPtr { private: static auto_ptr<CSingletonAutoPtr> m_auto_ptr; static CSingletonAutoPtr* m_instance; protected: CSingletonAutoPtr(); CSingletonAutoPtr(const CSingletonAutoPtr&); virtual ~CSingletonAutoPtr(); //allow auto_ptr to delete, using protected ~CSingletonAutoPtr() friend class auto_ptr<CSingletonAutoPtr>; public: static CSingletonAutoPtr* GetInstance(); void Test(); };
#p# は、次の SingletonAutoPtr.cpp に対応します:
#include "SingletonAutoPtr.h" #include <iostream> //initial static member vars here CSingletonAutoPtr* CSingletonAutoPtr::m_instance = NULL; auto_ptr<CSingletonAutoPtr> CSingletonAutoPtr::m_auto_ptr; ///////////////////////////////////////// // Construction/Destruction ///////////////////////////////////////// CSingletonAutoPtr::CSingletonAutoPtr() { cout << "CSingletonAutoPtr::CSingletonAutoPtr()" << endl; //put single object into auto_ptr object m_auto_ptr = auto_ptr<CSingletonAutoPtr>(this); } CSingletonAutoPtr::~CSingletonAutoPtr() { cout << "CSingletonAutoPtr::~CSingletonAutoPtr()" << endl; } CSingletonAutoPtr* CSingletonAutoPtr::GetInstance() { //begin lock //.... if(m_instance == NULL) m_instance = new CSingletonAutoPtr(); //end lock //... return m_instance; } void CSingletonAutoPtr::Test() { cout << "CSingletonAutoPtr::Test()" << endl; }
メソッドの呼び出し:
CSingletonAutoPtr* pSingleton = CSingletonAutoPtr::GetInstance(); pSingleton->Test();
C++ でシングルトンを記述するには、予想を超える多大な労力が必要です。 auto_ptr を使用したことがない人も多く、std:auto_ptr 自体はオブジェクト所有権メカニズムに基づいています。これとは対照的に、Apache Log4cxx にはオブジェクトのカウントに基づいた auto_ptr があります。 。適切な auto_ptr を使用するためだけに log4cxx を使用しなければならないのは、多くのプロジェクトにとって良いことではありません。もちろん、上記の例を記述するには、ANSI C++ の STL の std:auto_ptr で十分です。
#p#もう 1 つのアイデアは、GetInstance 関数を静的メンバーとして設計する方がよいということです。一般的に言えば、Singleton オブジェクトは大きくないためです。静的メンバーは常にメモリを占有する必要がありますが、それは大きな問題ではありません。ここでのデストラクターは public に設定する必要があります。以下はヘッダーファイルです。SingleStaticObj.h
class CSingletonStaticObj { private: static CSingletonStaticObj m_instance; protected: CSingletonStaticObj(); CSingletonStaticObj(const CSingletonStaticObj&); public: virtual ~CSingletonStaticObj(); //must public static CSingletonStaticObj& GetInstance(); void Test(); }; 对应的 SingleStaticObj.cpp 文件为: #include "SingletonStaticObj.h" #include <string> #include <iostream> using namespace std; CSingletonStaticObj CSingletonStaticObj::m_instance; CSingletonStaticObj::CSingletonStaticObj() { cout << "CSingletonStaticObj::CSingletonStaticObj()" << endl; } CSingletonStaticObj::~CSingletonStaticObj() { cout << "CSingletonStaticObj::~CSingletonStaticObj()" << endl; } CSingletonStaticObj& CSingletonStaticObj::GetInstance() { return m_instance; } void CSingletonStaticObj::Test() { cout << "CSingletonStaticObj::Test()" << endl; }
呼び出しメソッド:
CSingletonStaticObj& singleton = CSingletonAutoPtr::GetInstance();singleton.Test();
コードサイズの観点から、静的メンバー ref を使用した方が簡単なようです。私はこの方法の方が好きです。
ただし、静的メンバー シングルトンはすべての状況に適しているわけではありません。たとえば、GetInstance は、異なるインスタンスを返すことを動的に決定する必要がある場合には使用できません。たとえば、FileSystem::GetInstance は、Windows で実行する場合は新しい WinFileSystem を返す必要があり、Linux/Unix で実行する場合は新しい LinuxFileSystem を返す必要がある場合があります。この場合でも、シングルトン ポインターを含む上記の auto_ptr メソッドを使用する必要があります。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









c言語のシンボルの使用方法は、算術、割り当て、条件、ロジック、ビット演算子などをカバーします。算術演算子は基本的な数学的操作に使用されます。割り当てと追加、下位、乗算、除算の割り当てには、条件操作に使用されます。ポインター、ファイル終了マーカー、および非数値値。

Cでは、文字列でCharタイプが使用されます。1。単一の文字を保存します。 2。配列を使用して文字列を表し、ヌルターミネーターで終了します。 3。文字列操作関数を介して動作します。 4.キーボードから文字列を読み取りまたは出力します。

C言語では、以下などのエスケープシーケンスを通じて特殊文字が処理されます。\ nはラインブレークを表します。 \ tはタブ文字を意味します。 ESACEシーケンスまたは文字定数を使用して、Char C = '\ n'などの特殊文字を表します。バックスラッシュは2回逃げる必要があることに注意してください。さまざまなプラットフォームとコンパイラが異なるエスケープシーケンスを持っている場合があります。ドキュメントを参照してください。

マルチスレッドと非同期の違いは、マルチスレッドが複数のスレッドを同時に実行し、現在のスレッドをブロックせずに非同期に操作を実行することです。マルチスレッドは計算集約型タスクに使用されますが、非同期はユーザーインタラクションに使用されます。マルチスレッドの利点は、コンピューティングのパフォーマンスを改善することですが、非同期の利点はUIスレッドをブロックしないことです。マルチスレッドまたは非同期を選択することは、タスクの性質に依存します。計算集約型タスクマルチスレッド、外部リソースと相互作用し、UIの応答性を非同期に使用する必要があるタスクを使用します。

Char Arrayは文字シーケンスをC言語で保存し、char array_name [size]として宣言されます。アクセス要素はサブスクリプト演算子に渡され、要素は文字列のエンドポイントを表すnullターミネーター「\ 0」で終了します。 C言語は、strlen()、strcpy()、strcat()、strcmp()など、さまざまな文字列操作関数を提供します。

C言語では、charとwchar_tの主な違いは文字エンコードです。CharはASCIIを使用するか、ASCIIを拡張し、WCHAR_TはUnicodeを使用します。 Charは1〜2バイトを占め、WCHAR_Tは2〜4バイトを占有します。 charは英語のテキストに適しており、wchar_tは多言語テキストに適しています。 CHARは広くサポートされており、WCHAR_TはコンパイラとオペレーティングシステムがUnicodeをサポートするかどうかに依存します。 CHARの文字範囲は限られており、WCHAR_Tの文字範囲が大きく、特別な機能が算術演算に使用されます。

C言語では、charタイプの変換は、キャスト:キャスト文字を使用することにより、別のタイプに直接変換できます。自動タイプ変換:あるタイプのデータが別のタイプの値に対応できる場合、コンパイラは自動的に変換します。

C言語に組み込みの合計機能はないため、自分で書く必要があります。合計は、配列を通過して要素を蓄積することで達成できます。ループバージョン:合計は、ループとアレイの長さを使用して計算されます。ポインターバージョン:ポインターを使用してアレイ要素を指し示し、効率的な合計が自己概要ポインターを通じて達成されます。アレイバージョンを動的に割り当てます:[アレイ]を動的に割り当ててメモリを自分で管理し、メモリの漏れを防ぐために割り当てられたメモリが解放されます。
