トップページ – Modern C++編 C++編](../../index.html) – 第2章
問題① コピーやムーブに関するメンバ関数を定義したりしなかったりすることで、std::swap関数の挙動がどう変わるか確認してください。
ムーブコンストラクタ、ムーブ代入演算子が使えるのならば、これが使われます。
#include <iostream>
#include <utility>
class MyClass {
public:
(int v) : mValue(v) {}
MyClass(const MyClass& rhs) : mValue(rhs.mValue)
MyClass{
std::cout << "copy construtor" << std::endl;
}
(MyClass&& rhs) : mValue(rhs.mValue)
MyClass{
std::cout << "move construtor" << std::endl;
}
~MyClass() = default;
& operator=(const MyClass& rhs)
MyClass{
std::cout << "copy" << std::endl;
= rhs.mValue;
mValue return *this;
}
& operator=(MyClass&& rhs)
MyClass{
std::cout << "move" << std::endl;
if (this != &rhs) {
= rhs.mValue;
mValue }
return *this;
}
inline int GetValue() const
{
return mValue;
}
private:
int mValue;
};
int main()
{
(10);
MyClass a(20);
MyClass bstd::swap(a, b);
std::cout << a.GetValue() << ", " << b.GetValue() << std::endl;
}
実行結果:
move construtor
move
move
20, 10
ムーブコンストラクタとムーブ代入演算子が無ければ、コピーが使われます。
#include <iostream>
#include <utility>
class MyClass {
public:
(int v) : mValue(v) {}
MyClass(const MyClass& rhs) : mValue(rhs.mValue)
MyClass{
std::cout << "copy construtor" << std::endl;
}
~MyClass() = default;
& operator=(const MyClass& rhs)
MyClass{
std::cout << "copy" << std::endl;
= rhs.mValue;
mValue return *this;
}
inline int GetValue() const
{
return mValue;
}
private:
int mValue;
};
int main()
{
(10);
MyClass a(20);
MyClass bstd::swap(a, b);
std::cout << a.GetValue() << ", " << b.GetValue() << std::endl;
}
実行結果:
copy construtor
copy
copy
20, 10
ここで、ムーブコンストラクタとムーブ代入演算子を「= delete」で削除した場合は、コンパイルエラーになります。基本的にムーブを使用としますから、ムーブコンストラクタやムーブ代入演算子を呼び出そうとしますが、これが削除されていたら、その時点でコンパイルエラーになります(【言語解説】第10章)。
#include <iostream>
#include <utility>
class MyClass {
public:
(int v) : mValue(v) {}
MyClass(const MyClass& rhs) : mValue(rhs.mValue)
MyClass{
std::cout << "copy construtor" << std::endl;
}
(MyClass&& rhs) = delete;
MyClass
~MyClass() = default;
& operator=(const MyClass& rhs)
MyClass{
std::cout << "copy" << std::endl;
= rhs.mValue;
mValue return *this;
}
& operator=(MyClass&& rhs) = delete;
MyClass
inline int GetValue() const
{
return mValue;
}
private:
int mValue;
};
int main()
{
(10);
MyClass a(20);
MyClass bstd::swap(a, b);
std::cout << a.GetValue() << ", " << b.GetValue() << std::endl;
}
問題② int型はムーブによる生成や、ムーブ代入ができますか? また、const int型ならどうでしょうか?
int型のような標準の型はムーブできますが、const が付いていたら変更不能なため、ムーブ代入の代入先になることができません。このことは実際に試してみれば一目瞭然です。
#include <iostream>
#include <utility>
int main()
{
int a = 10;
int b = std::move(a); // OK
= std::move(b); // OK
a
const int ca = 10;
const int cb = std::move(ca); // OK
= std::move(cb); // コンパイルエラー。const変数は書き換えられない
ca }
std::is_move_constructible と std::is_move_assignable を使って調べてみましょう。
#include <iostream>
#include <type_traits>
int main()
{
std::cout << std::is_move_constructible<int>::value << " "
<< std::is_move_assignable<int>::value << std::endl;
std::cout << std::is_move_constructible<const int>::value << " "
<< std::is_move_assignable<const int>::value << std::endl;
}
実行結果:
1 1
1 0
予定どおりの結果が得られました。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |