こうやって std::swap
はC++ 11のように見えます:
template<typename T>
void swap(T& x, T& y)
{
T z = std::move(x);
x = std::move(y);
y = std::move(z);
}
私はまだ専門化する必要がありますかstd::swap
自分のタイプの場合、またはstd::swap
もちろん、私のクラスが移動コンストラクタと移動代入演算子を定義している限り、効率は最高になりますか?
std::swap
の特殊化はオプションになりましたが、非推奨ではありません。理論的根拠はパフォーマンスです。
プロトタイピングコードの場合、さらには多くの出荷コードの場合でも、std::swap
は十分高速です。ただし、コードを少しずつ調べる必要がある場合でも、カスタムスワップを作成すると、パフォーマンスが大幅に向上します。
クラスに基本的に1つの所有ポインターがあり、移動コンストラクターと移動割り当てがその1つのポインターを処理する必要がある場合を考えてみます。メンバーごとにマシンのロードとストアをカウントします。
移動コンストラクタ:1つのロードと2つのストア。
移動割り当て:2つのロードと2つのストア。
カスタムスワップ:2つのロードと2つのストア。
std::swap
は、1つの移動構築と2つの移動割り当て、または5つのロードと6つのストアです。
カスタムスワップは、std::swap
よりも2倍または3倍高速である可能性があります。負荷とストアを数えることで何かの速度を計算しようとしているときはいつでも、どちらも速く邪悪になります。
注:移動割り当てのコストを計算するときは、移動元の値(std::swap
アルゴリズム)に移動することを確認してください。これは、ブランチを犠牲にしても、割り当て解除のコストを無効にすることがよくあります。
移動のセマンティクスがあるので、特殊化
std::swap
は廃止されましたか?
いいえ。これは汎用バージョンですが、3番目の移動操作をスキップするように最適化できます。私の好みはcopy-and-swapイディオムとクラスのstd::swap
のカスタマイズを組み合わせることです。
それは私が持っていることを意味します:
class Aaaa
{
public:
Aaaa(); // not interesting; defined elsewhere
Aaaa(Aaaa&& rvalueRef); // same
Aaaa(const Aaaa& ref); // same
~Aaaa(); // same
Aaaa& operator=(Aaaa object) // copy&swap
{
swap(object);
return *this;
}
void swap(Aaaa& other)
{
std::swap(dataMember1, other.dataMember1);
std::swap(dataMember2, other.dataMember2);
// ...
}
// ...
};
namespace std
{
template<> inline void std::swap(Aaaa& left, Aaaa& right)
{ left.swap(right); }
}
それはあなたのタイプに依存します。
Xからz、yからx、zからyに移動します。これは、基礎となる表現の3つのコピー操作です(たった1つのポインター、おそらくそれ以上の、知っている人)。
今、あなたはあなたのタイプのためのより速いスワップを作成することができます(xorスワップトリック、インラインアセンブラ、またはおそらくあなたの基礎となるタイプのためのstd :: swapはただより速いです)。
または、コンパイラーも最適化に優れており、本質的に両方のケースを同じ命令に最適化します(レジスターにテンポラリを含めるなど)。
私は個人的には常に、移動割り当てなどのいくつかの場所から呼び出されるスワップメンバー関数を実装する傾向がありますが、YMMVです。
このswap()
は、移動コンストラクターと2つの移動割り当てを呼び出します。私は彼の特定のタイプのクラスに対して、より効率的なswap()
を書くことができると思います、
class X
{
int * ptr_to_huge_array;
public:
// ctors, assgn ops. etc. etc.
friend void swap(X& a, X& b)
{
using std::swap;
swap(a.ptr_to_huge_array, b.ptr_to_huge_array);
}
};
移動コンストラクタと代入演算子の実装に関係なく。