C++プログラマ キャスブログ
前のページ 1 2 3 4 5 6 次のページ
[C++11]右辺値参照とムーブセマンティクス 2015年05月14日22:53:08
簡単に説明すると一時オブジェクトのポインタの所有権の移動です。 何ができるかといえば、インスタンスを返す関数のコピーコンストラクタを 走らせずに済むということができます。 効果としては、メモリ確保・解放とコピーのコストを無くせます。 あくまでポインタの所有権の移動なので、ポインタを含まないクラスのインスタンスは コピーコンストラクタと変わりありません。 コードを書くとこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <cstdio> class Test { private: int* m_Int; public: // コンストラクタ Test() { m_Int = new int; printf( "コンストラクタ: %p\n", m_Int ); } // ムーブコンストラクタ(所有権の移動に必要なコンストラクタ) Test(Test&& obj) { m_Int = obj.m_Int; // ポインタの所有権の移動 obj.m_Int = nullptr; // nullptrを入れないと多重解放になります。 printf( "ムーブコンストラクタ: %p\n", m_Int ); } // デストラクタ virtual ~Test() { printf( "デストラクタ: %p\n", m_Int ); if( m_Int != nullptr ) { delete m_Int; m_Int = nullptr; } } }; Test Instance() { Test instance; // Step.1 コンストラクタ return instance; // Step.2 ムーブコンストラクタ // Step.3 instanceのデストラクタ } int main() { Test test = Instance(); // Instance関数の中で確保したアドレスを受け取れる return 0; // Step.4 testのデストラクタ }
これでインスタンスを返す関数を作っても安心ですね。 補足情報として、自分で作ったクラスであればムーブコンストラクタの実装は可能ですが 標準ライブラリや、その他内部構造を知りたくないものについては強制的にムーブコンス トラクタを呼び出す機能があります。 それがstd::moveです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <cstdio> #include <vector> #include <utility> //std::moveに必要なヘッダ class Test { private: std::vector<int> m_Vector; public: // コンストラクタ Test() { m_Vector.resize( 1000 ); printf( "コンストラクタ: %p\n", &m_Vector[0] ); } // ムーブコンストラクタ(所有権の移動に必要なコンストラクタ) Test(Test&& obj) { m_Vector = std::move( obj.m_Vector ); // 所有権の移動 // m_Vector = obj.m_Vector; こう書くとコピーコンストラクタが走るのでダメです。 printf( "ムーブコンストラクタ: %p\n", &m_Vector[0] ); } }; Test Instance() { Test instance; return instance; } int main() { Test test = Instance(); // Instance関数の中で確保したアドレスを受け取れる return 0; }
便利ですね。 言葉ばかりややこしい右辺値参照とムーブセマンティクスですが中身は大したことないです。
[C++]オーバーロードをするとメンバの順列が変わる 2015年01月22日02:10:12
純仮想関数のみのクラス(インターフェース)を作成しDLLを 通じて実装したクラスのインスタンスの取得を行っていました。
1 2 3 4 5 6 class ITest { public: virtual ~ITest(){}; // デストラクタ virtual void Print() = 0; };
ある日、機能拡張が必要となりインターフェースに オーバーロードしたメソッドを追加しました。 最後部にメソッドを追加すれば、上位互換を保てると思い実施しましたが オーバーロードすると仮想関数の順列が変わるようで失敗しました。
1 2 3 4 5 6 7 8 // オーバーロードを行って上位互換が保てなかった例 class ITest { public: virtual ~ITest(){}; // デストラクタ virtual void Print() = 0; virtual void Print(int i) = 0; };
メソッド名を変更すると上位互換を保ったまま正常に動作しました。 ご利用は計画的に!
1 2 3 4 5 6 7 8 // メソッド名を変更して対応 class ITest { public: virtual ~ITest(){}; // デストラクタ virtual void Print() = 0; virtual void PrintInt(int i) = 0; };
[C++]クラスのインスタンスなんてダミー 2014年12月30日07:12:20
C++はオブジェクト指向言語といいつつも 内部の実装は関数と関数ポインタばかりです。 試しにこんな実験です。 インスタンスがnullであっても実態は関数にthisポインタと 呼ばれる自身のポインタを渡して呼び出しているだけです。 メンバ変数にアクセスしない限りメンバメソッドは呼び放題です。(ただしvirtualは除く) ※危険なのでよい子は真似しないでくださいね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <cstdio> // printfに必要なヘッダー class A { public: void print() { printf( "%p test\n", this ); } // 見えませんが実態はこんな感じの引数がついています。 // ※注 イメージ // void print(A* this) }; int main() { A* a = nullptr; // C++11でなければNULL a->print(); // 見えませんがこんな感じの呼ばれ方です。 // ※注 イメージ // A::print( a ); return 0; }
出力: 00000000 test
前のページ 1 2 3 4 5 6 次のページ
カテゴリ

リンク
C++11のコードを
試すのに便利です。
http://ideone.com/

同人ゲームを
製作している知人
sorcery

にほんブログ村 IT技術ブログ C/C++へ
にほんブログ村


C++ ブログランキングへ

ゲームダウンロード DefenceTri