|
|
[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;
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;
return instance;
}
int main()
{
Test test = Instance();
return 0;
} |
これでインスタンスを返す関数を作っても安心ですね。
補足情報として、自分で作ったクラスであればムーブコンストラクタの実装は可能ですが
標準ライブラリや、その他内部構造を知りたくないものについては強制的にムーブコンス
トラクタを呼び出す機能があります。
それが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>
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 );
printf( "ムーブコンストラクタ: %p\n", &m_Vector[0] );
}
};
Test Instance()
{
Test instance;
return instance;
}
int main()
{
Test test = 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>
class A
{
public:
void print()
{
printf( "%p test\n", this );
}
};
int main()
{
A* a = nullptr;
a->print();
return 0;
} |
出力:
00000000 test |
|
|