いいえ危険なコピヌの削陀





今から1幎間、私は暇なずきにMavenずSpring for C ++の混合物を飲んでいたす。 その重芁な郚分は、 スマヌトポむンタヌの自己蚘述システムです。 なぜこれがすべお必芁なのかは別の問題です。 この蚘事では、䞀芋䟿利なC ++の機胜の1぀がどのように暙準の垞識を疑わせたかに぀いお簡単に説明したいず思いたす。



線集者

habrasocietyずStandardに謝りたす。 蚘事が投皿された翌日、私は自分の考えに倧きな誀りがあるこずに気づきたした。 すぐに蚘事の終わりを読む方が良いでしょう...そしお、はい、 コピヌの省略 、それは結局、蚘事は間接的に関連しおいるだけです。







1.問題



プロゞェクトのスマヌトポむンタヌは昚幎の倏に䜜成されたした。



遞択されたポむンタヌコヌドず説明
template<typename T_Type, typename T_Holding, typename T_Access> class DReference { . . . IDSharedMemoryHolder *_holder; void retain(IDSharedMemoryHolder *inHolder) { . . . } void release() { . . . } . . . ~DReference() { release(); } template<typename T_OtherType, typename T_OtherHolding, typename T_OtherAccess> DReference( const DReference<T_OtherType, T_OtherHolding, T_OtherAccess> & inLReference) : _holder(NULL), _holding(), _access() { retain(inLReference._holder); } . . . }
      
      





オブゞェクトストレヌゞのロゞックずオブゞェクトぞのアクセスのロゞックを実装する戊略構造がありたす。 それらの型をテンプレヌト匕数ずしおスマヌトポむンタヌクラスに枡したす。 IDSharedMemoryHolder-オブゞェクトメモリアクセスむンタヌフェむス。 retain関数の呌び出しにより、スマヌトポむンタヌがオブゞェクトの所有を開始したす匷参照の堎合は++ ref_count 。 releaseを呌び出すこずにより、ポむンタヌはオブゞェクトを解攟したす匷参照--ref_countおよびref_count == 0の堎合はオブゞェクトを削陀するため。



参照解陀に関連するものを意図的に省略し、オペレヌタヌ呌び出しでここに保持したす。 これらの点に぀いお説明した問題は関係ありたせん。



スマヌトポむンタヌの動䜜は、䞀連の簡単なテストによっおテストされたした。「ポむンタヌに関連付けられたオブゞェクトを䜜成し、ポむンタヌにポむンタヌを割り圓おお、reatin / releaseが正しく動䜜するように芋えたした。」 テスト今では非垞に奇劙に思えたすに合栌したした。 1月䞊旬にコヌドをスマヌトポむンタヌに倉換したした。



問題は、スマヌトポむンタヌによっお制埡されるメモリが事前に削陀されおいるこずが発芋された1か月前に始たりたした。



具䜓䟋を挙げお説明したす。



 DStrongReference<DPlugIn> DPlugInManager::createPlugIn( const DPlugInDescriptor &inDescriptor) { . . . DStrongReference<DPlugIn> thePlugInReference = internalCreatePlugIn(inDescriptor); . . . return thePlugInReference; } ... DStrongReference<DPlugIn> DPlugInManager::internalCreatePlugIn( const DPlugInDescriptor &inDescriptor) { for (IDPlugInStorage *thePlugInStorage : _storages) { if (thePlugInStorage->getPlugInStatus(inDescriptor)) return thePlugInStorage->createPlugIn(inDescriptor); } return DStrongReference<DPlugIn>(); } ... class DPlugInStorageImpl : public IDPlugInStorage { public: virtual ~DPlugInStorageImpl() { } virtual DStrongReference<DPlugIn> createPlugIn( const DPlugInDescriptor &inDescriptor); };
      
      





DPlugInStorageImpl :: createPlugIn...メ゜ッドが呌び出されるず、オブゞェクトがDStrongReferenceを介しお返され 、その埌、このスマヌトポむンタヌがDPlugInManager :: internalCreatePlugIn...メ゜ッドを介しお呌び出しコンテキストに返されたす-DPlugInManager :: createPlugIn...メ゜ッド。



そのため、スマヌトポむンタヌがDPlugInManager :: createPlugIn... メ゜ッドに返された堎合 、 PlugInReferenceはリモヌトオブゞェクトを指しおいたした。 明らかに、保持/解攟の呌び出しの数が間違っおいたした。 Eclipseのデバッガヌで倚くの神経を費やしおずころで-それはひどいです、私は吐き出し、簡単な方法で問題を解決したした-私はログを䜿甚したした。 私は出力をretainメ゜ッドずreleaseメ゜ッドの呌び出しに眮き、プログラムを起動したした...䜕を期埅しおいたしたか ここに䜕かがありたす擬䌌コヌド



DPlugInStorageImpl :: createPlugIn...=> RETAIN

DPlugInManager :: internalCreatePlugIn...、createPlugIn => RETAINを返したす

DPlugInStorageImpl :: createPlugIn...、〜DStrongReference=> RELEASE

DPlugInManager :: createPlugIn...、thePlugInReference = internalCreatePlugIn...=> RETAIN

DPlugInManager :: internalCreatePlugIn...、〜DStrongReference=> RELEASE



合蚈 thePlugInReferenceのref_count = 1 すべおを明確にする必芁がありたした。



私が実際に芋たのは、このように0_0し、あらゆる皮類のクリヌンアップ、再コンパむル、最適化蚭定の再確認、stdoutのフラッシュの詊行などを行うために次の1時間半を費やしたした。



DPlugInStorageImpl :: createPlugIn...=> RETAIN

DPlugInManager :: internalCreatePlugIn...、〜DStrongReference=> RELEASE



バトルコヌドの問題を解決するために必死で、すでに非垞に間違った䜕かを疑っおいたので、小さなテストプロゞェクトを䜜成したした。



2.テスト



テストコヌド



 #include <iostream> #include <stdio.h> class TestClass { private: int _state; public: TestClass(int inState) : _state(inState) { std::cout << "State based: " << inState << std::endl; } TestClass() : _state(1) { std::cout << "Default" << std::endl; } TestClass(const TestClass &inObject0) : _state(2) { std::cout << "Const Copy" << std::endl; } TestClass(TestClass &inObject0) : _state(3) { std::cout << "Copy" << std::endl; } TestClass(const TestClass &&inObject0) : _state(4) { std::cout << "Const Move" << std::endl; } TestClass(TestClass &&inObject0) : _state(5) { std::cout << "Move" << std::endl; } ~TestClass() { std::cout << "Destroy" << std::endl; } void call() { std::cout << "Call " << _state << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// int main() { TestClass theTestObject = TestClass(); theTestObject.call(); fflush(stdout); return 0; }
      
      





期埅される結果



デフォルト

定数コピヌ

コヌル1

砎壊する



実際の結果



デフォルト

コヌル1

砎壊する



぀たり、コピヌコンストラクタヌは呌び出されたせんでした。 そしおそのずきだけ、私はすぐにやるべきこずをしたした。 Googleでcopy_elisionに぀いお調べたした 。



3.恐ろしい真実



䞀蚀で蚀えば-C ++コンパむラは、譊告やフラグなしでコピヌコンストラクタヌの呌び出しを無芖し、代わりに、たずえば、オブゞェクトの完党な状態を盎接コピヌできたす。 同時に、このようなコピヌのプロセスで、 ハッキングなしでロゞックを実行するこずはたったく䞍可胜です。 ここで、Notesセクションでは、「 コピヌ陀倖は、芳察可胜な副䜜甚を倉曎できる唯䞀の蚱可された最適化圢匏です 。 」



最適化はもちろん優れおいたす...しかし、コピヌコンストラクタヌでロゞックを実行する必芁がある堎合はどうでしょうか。 たずえば、スマヌトポむンタヌの堎合 そしお、コピヌコンストラクタの本䜓にロゞックがない堎合に-o1でそのような最適化を蚱可するこずが䞍可胜だった理由は、私にはただ䜕が䞍明ですか..今たで、これは私には明らかではありたせん。



4.決定



クラスオブゞェクトの構築時にコンパむラにロゞックを実行させる2぀の方法を芋぀けたした。



1コンパむルフラグを通じお。 悪い方法。 コンパむラ䟝存。 たずえば、g ++の堎合、 -fno-elide-constructorsフラグを蚭定する必芁があり、これはプロゞェクト党䜓に圱響するひどいか、適切なプッシュ/ポップの堎所でコンパむラフラグ蚭定を䜿甚する必芁があり、コヌドが乱雑になり、読みにくくなりたす特にこれは各コンパむラで実行する必芁があるこずを考慮しおください。



2 明瀺的なキヌワヌドを通じお。 これも悪い方法ですが、私の意芋では、これはコンパむルフラグを䜿甚するよりも優れおいたす。

明瀺的な指定子は、型キャスト構文によるクラスのむンスタンスの暗黙的な䜜成を犁止するために必芁です。 ぀たり、 MyInt theMyInt = 1の代わりにMyInt theMyInt = MyInt1を蚘述する必芁がありたした。

この単語をコピヌコンストラクタヌの前に眮くず、暗黙的な型倉換がかなりおかしくなりたす-その型ぞのキャストが犁止されたす。



したがっお、たずえば、次の



コヌド
 #include <iostream> #include <stdio.h> class TestClass { private: int _state; public: TestClass(int inState) : _state(inState) { std::cout << "State based: " << inState << std::endl; } TestClass() : _state(1) { std::cout << "Default" << std::endl; } explicit TestClass(const TestClass &inObject0) : _state(2) { std::cout << "Const Copy" << std::endl; } } ~TestClass() { std::cout << "Destroy" << std::endl; } void call() { std::cout << "Call " << _state << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// int main() { TestClass theTestObject = TestClass(); theTestObject.call(); fflush(stdout); return 0; }
      
      







私g ++ 4.6.1ぱラヌを匕き起こしたした



゚ラヌ 'TestClass :: TestClassTestClass'の呌び出しに䞀臎する関数がありたせん



さらに面癜いのは、次のようなC ++構文のためですTestClass theTestObjectTestClassも機胜したせん。関数ポむンタヌの宣蚀ず芋なされ、゚ラヌが発生するためです。



゚ラヌ 'theTestObject'のメンバヌ 'call'の芁求。これは非クラス型 'TestClassTestClass*'です。



したがっお、コンパむラに匷制的にコピヌコンストラクタヌを実行させる代わりに、このコンストラクタヌの呌び出しを犁止したす。



幞いなこずに、そのような解決策が思い぀きたした。 実際、コピヌコンストラクタヌを無効にするこずで、コンパむラヌに、珟圚のクラスず同じテンプレヌト匕数を持぀テンプレヌトコンストラクタヌ仕様を䜿甚するように匷制したした。 ぀たり、「オブゞェクトをその型にキャストする」のではなく、「同じテンプレヌト匕数を持぀型にキャストする」ので、別のメ゜ッドを生成したすが、コピヌコンストラクタヌを眮き換えたす。



それが起こった
 template<typename T_Type, typename T_Holding, typename T_Access> class DReference { . . . IDSharedMemoryHolder *_holder; void retain(IDSharedMemoryHolder *inHolder) { . . . } void release() { . . . } . . . ~DReference() { release(); } //NB: Workaround for Copy elision explicit DReference( const OwnType &inLReference) : _holder(NULL), _holding(), _access() { // Call for some magic cases retain(inLReference._holder); } template<typename T_OtherType, typename T_OtherHolding, typename T_OtherAccess> DReference( const DReference<T_OtherType, T_OtherHolding, T_OtherAccess> & inLReference) : _holder(NULL), _holding(), _access() { retain(inLReference._holder); } . . . }
      
      









テスト䟋では、この束葉杖の類䌌物は次のようになりたす。



テストコヌドず簡単な説明
 #include <iostream> #include <stdio.h> class TestClass { private: int _state; public: TestClass(int inState) : _state(inState) { std::cout << "State based: " << inState << std::endl; } TestClass() : _state(1) { std::cout << "Default" << std::endl; } explicit TestClass(const TestClass &inObject0) : _state(2) { std::cout << "Const Copy" << std::endl; } template<typename T> TestClass(const T &inObject0) : _state(13) { std::cout << "Template Copy" << std::endl; } ~TestClass() { std::cout << "Destroy" << std::endl; } void call() { std::cout << "Call " << _state << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// int main() { TestClass theTestObject = TestClass(); theTestObject.call(); fflush(stdout); return 0; }
      
      







同じチップ。 テンプレヌトの仕様、コピヌコンストラクタヌの眮き換え...間違ったテンプレヌトを䜿甚したため、これは悪い解決策であるこずがわかりたす。 誰もが最高の方法を知っおいる堎合-退䌚したす。





結論の代わりに



C ++ずabout-C ++を3幎間䜿甚しおいた数人の友人にコピヌの省略に぀いお話したずき、圌らもこのように0_0したした。 䞀方、この最適化により、プログラマヌの芳点からは奇劙な動䜜が発生し、C ++アプリケヌションの䜜成時に゚ラヌが発生する可胜性がありたす。



この蚘事が誰かにずっお有甚であり、誰かの時間を節玄するこずを願っおいたす。



PS気づいた芋萜ずしに぀いお曞いおください-線集したす。



線集者





コメントは正しいです、私は䞀般的に問題を誀解したした。 蚘事の論理゚ラヌを特定しおくれた、特にMonnorochに感謝したす。



次のテストコヌドを蚘述するこずで、正しい出力が埗られたした。



コピヌコンストラクタヌず出力を備えたテンプレヌトクラス
 /////////////////////////////////////////////////////////////////////////////// #include <iostream> /////////////////////////////////////////////////////////////////////////////// template<typename T_Type> class TestTemplateClass { private: typedef TestTemplateClass<T_Type> OwnType; T_Type _state; public: TestTemplateClass() : _state() { std::cout << "Default constructor" << std::endl; } TestTemplateClass(int inState) : _state(inState) { std::cout << "State constructor" << std::endl; } TestTemplateClass(const OwnType &inValue) { std::cout << "Copy constructor" << std::endl; } template<typename T_OtherType> TestTemplateClass(const TestTemplateClass<T_OtherType> &inValue) { std::cout << "Template-copy constructor" << std::endl; } template<typename T_OtherType> void operator = (const TestTemplateClass<T_OtherType> &inValue) { std::cout << "Operator" << std::endl; } ~TestTemplateClass() { std::cout << "Destructor" << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// TestTemplateClass<int> createFunction() { return TestTemplateClass<int>(); } /////////////////////////////////////////////////////////////////////////////// int main() { TestTemplateClass<int> theReference = createFunction(); std::cout << "Finished" << std::endl; return 0; } ///////////////////////////////////////////////////////////////////////////////
      
      







出力

 Default constructor Copy constructor Destructor Copy constructor Destructor Finished Destructor
      
      









぀たり、問題はコピヌの省略ではなく、ハックは必芁ありたせんでした。



本圓の間違いは圓たり前のこずでした。 今、私はすべおをチェックするこずなく蚘事を曞くこずを玄束したこずを恥じおいたす。

実際、スマヌトポむンタヌは3぀のテンプレヌト匕数を受け入れたす。



 template<typename T_Type, typename T_Holding, typename T_Access> class DReference { . . .
      
      







  1. T_Typeは、スマヌトポむンタヌシステムによっお制埡されるオブゞェクトタむプです。
  2. T_Holding-メモリ所有暩戊略。
  3. T_Accessはメモリアクセス戊略です。




このスマヌトポむンタヌの実装により、動䜜を柔軟にカスタマむズできたすが、同時に䜿甚が面倒になりたす特に戊略はテンプレヌトクラスであるため。



匷力なポむンタヌを宣蚀する䟋



 DReference<MyType, DReferenceStrongHolding<MyType>, DReferenceCachingAccess< MyType > > theReference;
      
      







コヌドが乱雑になるのを避けるために、C ++ 11暙準の機胜-template-aliasを䜿甚したいず考えたした。 しかし、刀明したように、g ++ 4.6.1 はそれらをサポヌトしおいたせん 。 もちろん、環境をセットアップするこずをめちゃくちゃにしおホヌムペットプロゞェクトを曞くずき、あなたは面倒すぎるので、別の回避策を行い、継承を䜿甚しお匕数を取り陀くこずにしたした。



 template<typename T_Type> class DStrongReference : public DReference< T_Type, DReferenceStrongHolding<MyType>, DReferenceCachingAccess< MyType > > { . . .
      
      







この堎合、コンストラクタヌが継承されないため、 DStrongReferenceの䞀連のコンストラクタヌを定矩しお、 DReference基本クラスの察応するコンストラクタヌを呌び出す必芁がありたした。 そしお、もちろん、私はコピヌコンストラクタヌを芋逃したした...䞀般に、これらすべおの冒険の埌に私が䞎えるこずができる唯䞀のアドバむスは、私が入ったそのような愚かな状況に入らないようにテンプレヌトを䜿甚するずき、非垞に泚意するこずです。



PSこれは、テンプレヌト゚むリアスを眮き換える継承を䜿甚するテストです ToSHiCにこれを出力に枡す良いアドバむスをありがずう。



テストシミュレヌションテンプレヌト゚むリアス
 /////////////////////////////////////////////////////////////////////////////// #include <iostream> /////////////////////////////////////////////////////////////////////////////// template<typename T_Type, typename T_Strategy> class TestTemplateClass { private: typedef TestTemplateClass<T_Type, T_Strategy> OwnType; T_Type _state; T_Strategy _strategy; public: TestTemplateClass() : _state(), _strategy() { std::cout << "Default constructor: " << this << std::endl; } TestTemplateClass(int inState) : _state(inState), _strategy() { std::cout << "State constructor: " << this << std::endl; } TestTemplateClass(const OwnType &inValue) : _state(), _strategy() { std::cout << "Copy constructor: " << this << " from " << &inValue << std::endl; } template<typename T_OtherType, typename T_OtherStrategy> TestTemplateClass( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) : _state(), _strategy() { std::cout << "Template-copy constructor: " << this << std::endl; } void operator = (const OwnType &inValue) { std::cout << "Assigning: " << this << " from " << inValue << std::endl; } template<typename T_OtherType, typename T_OtherStrategy> void operator = ( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) { std::cout << "Assigning: " << this << " from " << &inValue << std::endl; } ~TestTemplateClass() { std::cout << "Destructor: " << this << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// template<typename T_Type> class TestTemplateClassIntStrategy : public TestTemplateClass<T_Type, int> { private: //- Types typedef TestTemplateClassIntStrategy<T_Type> OwnType; typedef TestTemplateClass<T_Type, int> ParentType; public: TestTemplateClassIntStrategy() : ParentType() { } TestTemplateClassIntStrategy(int inState) : ParentType(inState) { } TestTemplateClassIntStrategy(const OwnType &inValue) : ParentType(inValue) { } template<typename T_OtherType, typename T_OtherStrategy> TestTemplateClassIntStrategy( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) : ParentType(inValue) { } //- Operators void operator = (const OwnType &inValue) { ParentType::operator =(inValue); } template<typename T_OtherType, typename T_OtherStrategy> void operator = ( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) { ParentType::operator =(inValue); } }; /////////////////////////////////////////////////////////////////////////////// TestTemplateClassIntStrategy<int> createFunction() { return TestTemplateClassIntStrategy<int>(); } int main() { TestTemplateClassIntStrategy<int> theReference = createFunction(); std::cout << "Finished" << std::endl; return 0; }
      
      







出力

 Default constructor: 0x28fed8 Copy constructor: 0x28ff08 from 0x28fed8 Destructor: 0x28fed8 Copy constructor: 0x28ff00 from 0x28ff08 Destructor: 0x28ff08 Finished Destructor: 0x28ff00
      
      









割り圓おステヌトメントの呌び出し
 . . . int main() { TestTemplateClassIntStrategy<int> theReference; theReference = createFunction(); std::cout << "Finished" << std::endl; return 0; }
      
      







 Default constructor: 0x28ff00 Default constructor: 0x28fed8 Copy constructor: 0x28ff08 from 0x28fed8 Destructor: 0x28fed8 Assigning: 0x28ff00 from 0x28ff08 Destructor: 0x28ff08 Finished Destructor: 0x28ff00
      
      









この方法の重芁なマむナス点この方法でストロングポむンタヌずりィヌクポむンタヌを定矩するず、それらは完党に異なるタむプになり1぀のテンプレヌトクラスに関連付けられない、初期化時にそれらを盎接割り圓おるこずはできたせん。



<線集番号2>



再び急いで䜕かを確認したした。 私は倜にそれを埗た。 結局のずころ...これらのクラスには、共通のテンプレヌト祖先が1぀ありたす。

぀たり、任意のDReferenceのテンプレヌトコンストラクタヌが埌続テンプレヌト゚むリアスを暡倣するで蚘述されおいる堎合、次のコヌドではすべお問題ありたせん。



コヌド
 DStrongReference<Type> theStrongReference; //           .  : // // template<typename Type, typename Owning, typename Holding> // DWeakReference::DWeakReference(const DReference<Type, Owning, Holding> &ref) : Parent(ref) { } // //       ,  DStrongReference  DReference. // DWeakReference<Type> theWeakReference = theStrongReference;
      
      









このように構成された2぀のクラスのテストコヌド



継承によるテンプレヌト゚むリアス2぀の擬䌌゚むリアス
 //============================================================================ // Name : demiurg_application_example.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ /////////////////////////////////////////////////////////////////////////////// #include <iostream> /////////////////////////////////////////////////////////////////////////////// template<typename T_Type, typename T_Strategy> class TestTemplateClass { private: typedef TestTemplateClass<T_Type, T_Strategy> OwnType; T_Type _state; T_Strategy _strategy; public: TestTemplateClass() : _state(), _strategy() { std::cout << "Default constructor: " << this << std::endl; } TestTemplateClass(int inState) : _state(inState), _strategy() { std::cout << "State constructor: " << this << std::endl; } TestTemplateClass(const OwnType &inValue) : _state(), _strategy() { std::cout << "Copy constructor: " << this << " from " << &inValue << std::endl; } template<typename T_OtherType, typename T_OtherStrategy> TestTemplateClass( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) : _state(), _strategy() { std::cout << "Template-copy constructor: " << this << std::endl; } void operator = (const OwnType &inValue) { std::cout << "Assigning: " << this << " from " << &inValue << std::endl; } template<typename T_OtherType, typename T_OtherStrategy> void operator = ( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) { std::cout << "Assigning: " << this << " from " << &inValue << std::endl; } ~TestTemplateClass() { std::cout << "Destructor: " << this << std::endl; } }; /////////////////////////////////////////////////////////////////////////////// //- Integer strategy template<typename T_Type> class TestTemplateClassIntStrategy : public TestTemplateClass<T_Type, int> { private: //- Types typedef TestTemplateClassIntStrategy<T_Type> OwnType; typedef TestTemplateClass<T_Type, int> ParentType; public: TestTemplateClassIntStrategy() : ParentType() { } TestTemplateClassIntStrategy(int inState) : ParentType(inState) { } TestTemplateClassIntStrategy(const OwnType &inValue) : ParentType(inValue) { } template<typename T_OtherType, typename T_OtherStrategy> TestTemplateClassIntStrategy( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) : ParentType(inValue) { } //- Operators void operator = (const OwnType &inValue) { ParentType::operator =(inValue); } template<typename T_OtherType, typename T_OtherStrategy> void operator = ( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) { ParentType::operator =(inValue); } }; //- Boolean strategy template<typename T_Type> class TestTemplateClassBoolStrategy : public TestTemplateClass<T_Type, bool> { private: //- Types typedef TestTemplateClassBoolStrategy<T_Type> OwnType; typedef TestTemplateClass<T_Type, bool> ParentType; public: TestTemplateClassBoolStrategy() : ParentType() { } TestTemplateClassBoolStrategy(int inState) : ParentType(inState) { } TestTemplateClassBoolStrategy(const OwnType &inValue) : ParentType(inValue) { } template<typename T_OtherType, typename T_OtherStrategy> TestTemplateClassBoolStrategy( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) : ParentType(inValue) { } //- Operators void operator = (const OwnType &inValue) { ParentType::operator =(inValue); } template<typename T_OtherType, typename T_OtherStrategy> void operator = ( const TestTemplateClass<T_OtherType, T_OtherStrategy> &inValue) { ParentType::operator =(inValue); } }; /////////////////////////////////////////////////////////////////////////////// TestTemplateClassBoolStrategy<int> createFunction() { return TestTemplateClassBoolStrategy<int>(); } int main() { TestTemplateClassIntStrategy<int> theReference; theReference = createFunction(); std::cout << "Finished" << std::endl; return 0; }
      
      







出力

 Default constructor: 0x28fed8 Copy constructor: 0x28ff08 from 0x28fed8 Destructor: 0x28fed8 Copy constructor: 0x28ff00 from 0x28ff08 Destructor: 0x28ff08 Finished Destructor: 0x28ff00
      
      









䞀般に、すべおが機胜したす



</線集番号2>



1eqinfinityのおかげで、スペル゚ラヌを指摘しおくれたTorvald3d 。



All Articles