どうすればswap関数をC ++で高速化できますか?

私はC + +とカップルの文字列ソートアルゴリズムを書いていると私はこのスワップ操作を高速化することができますかと思う。

void swap(string *items,int a, int b ){
        string temp;
        temp = items[a];
        items[a] = items[b];
        items[b] = temp;
}

あなたが助けることができれば感謝します...

6
"早期の最適化がすべての悪の根源である、約95%の小さな効率を忘れるべきだ"〜Donald Knuth
追加された 著者 Lalaland,
各スワップには3つの文字列コピーが存在しますので、文字列が長いと問題が発生すると想定するのは間違いありません。
追加された 著者 Collin Dauphinee,
@GregHewgill、@VJo:Visual Studioではこれまでのことは分かりませんが、 std :: string の両方のインスタンスに明示的に指定しないかぎり、libstdc ++がこれを行うとは思いません。同じアロケータ。
追加された 著者 Collin Dauphinee,
無視して、gccが何をしているのか分かります。
追加された 著者 Collin Dauphinee,
@dauphic std :: stringの優れた実装はディープコピーを行わないため、上記はマイクロ最適化です。
追加された 著者 BЈовић,
@dauphic: string オブジェクトを割り当てることは、実装の詳細に応じてデータをコピーするとは限りません。たとえば、参照カウントコピーオンライトの実装では、文字列データのコピーが回避されます。
追加された 著者 Greg Hewgill,
あなたのプログラムのパフォーマンスのボトルネックと判断しましたか?なぜあなたはそれが遅いと思いますか?
追加された 著者 Seth Carnegie,
私はあなたのソートアルゴリズムがスロー操作ではなくスローになるようにスワップコールを呼び出す必要があると推測しています
追加された 著者 Esailija,
"しかし、我々は、その重要な3%で機会を譲るべきではありません。良いプログラマは、そのような推論によって自己満足に陥ることはないでしょう、彼は重要なコードを慎重に見て賢明になりますが、ドナルドクヌス
追加された 著者 chill,
コードはかなり小さいので、インラインで宣言できます。それはあなたに関数呼び出しを保存しますが、コードはより速く実行されますが、実行可能ファイルのサイズは少々増加します。
追加された 著者 xcrypt,

4 答え

Stringクラスには独自のスワップ機能があります。

items[a].swap(items[b]);

文字列の内部構造にアクセスし、すべてのコピーを避けるため、これを実行する最速の方法です。

こちらをご覧ください。

20
追加された
私は完全に std :: string がスワップをサポートしているのを忘れてしまっていますが、これはおそらくrvalue参照を持たない場合(おそらく良い場合)は最高の解決策です。
追加された 著者 Collin Dauphinee,
私は試して、私はより速い結果を得る。ありがとう...
追加された 著者 ibrahim,
@xcrypt:一般的な関数は、必要に応じて特定のクラスメソッドを呼び出す必要があります。
追加された 著者 sth,
これはもっと一般的な std :: swap()が内部的に行うものであることに注意してください。
追加された 著者 sth,
Gregの答えは、この関数が使用されることを保証することに注意してください。
追加された 著者 GManNickG,
これはこれまでのところ最高の答えです。+1
追加された 著者 Seth Carnegie,
@sth特定のクラスがSTLで同じ名前の関数を持つメソッドを持つ理由は、それらのメソッドが一般的なSTLテンプレート関数よりも特定のクラスで高速であるためです。私はどこかの本でそれを読む。
追加された 著者 xcrypt,

std :: swap()を使うことができます:

void swap(string *items, int a, int b) {
    std::swap(items[a], items[b]);
}

しかし、これがかなり速くなるという保証はなく、これはおそらくあなたのコードの遅い部分ではないでしょう。他のコードと比較してスワップ操作のパフォーマンスを測定しましたか?

9
追加された
@DavidHeffernan:私は std :: swap がより速くなることを期待します。特に、C ++ 11では、移動コンストラクタのセマンティクスが3つの割り当てよりも優れています。
追加された 著者 Greg Hewgill,
std :: swap がより速くなると期待していますか?もしそうなら、なぜですか?しかし、もっとも間違いなく std :: swap を使用し、独自のラッパーを書く必要はありません。
追加された 著者 David Heffernan,
その答えには必ず入るはずです
追加された 著者 David Heffernan,
私はこれが答えの代わりにコメントでなければならないとほとんど思っています。問題はそれをより速くする方法であり、これがより速くなるという保証はないということです。実際、これはすでに彼が行っているのとまったく同じことでしょう。
追加された 著者 Seth Carnegie,
あなたが正しいかどうかわからなくても正しい答えを得るために+ 1 + + + + C ++ 03の21.3.7.8では、文字列のために std :: swap がオーバーロードされ、 swap メンバ関数です。 21.3.5.8は、これが一定時間であることを保証する。移動セマンティクスのナンセンスはありません。質問者のコードよりも速いことを絶対に確信することはできませんが、 n の期待される O(n)から質問者のコードを保存するCOWやその他の最適化の可能性>は文字列の長さです。しかし、それはかなり良くなる可能性があり、それは確かに悪くない。
追加された 著者 Steve Jessop,

std :: swap を使用します。それはできる最高の仕事をするでしょう。コンパイラがC ++ 11のrvalue参照をサポートしている場合、スワップ機能で発生するコピーを回避するために移動セマンティクスを利用することを意味します。

ただし、コンパイラがrvalue参照をサポートしていない場合、スワップ関数と同じように実行される可能性が高くなります。

ほとんどの標準ライブラリの実装では、 std :: swap が次のように実装されます。

template
void swap(T& a, T& b) {
    T temp(std::move(a));
    a = std::move(b);
    b = std::move(temp);
}

The std::move function will return an rvalue reference (T&&) to the variable passed in. When you attempt to assign this rvalue reference, it will invoke the type's move operator, if one is available. If a move operator isn't available, it will invoke the copy operator as usual.

std :: string の場合、上記のスワップ関数はC ++ 11では文字列コピーを行いません。文字列長やC文字列ポインタなどの内部データのみがコピーされます。 C ++ 11がなければ、実際の文字列の内容を3つコピーします。

6
追加された
とにかく、文字列の std :: swap のオーバーロードがあります。 C ++ 03の21.3.7.8またはC ++の21.4.8.8 11。したがって、「C ++ 11なしでは、実際の文字列コンテンツの3つのコピーを実行します」というのは真実ではありません。
追加された 著者 Steve Jessop,

string の代わりに string * 型の要素を処理するようにアルゴリズムを変更することができます。 swap 関数内のすべての代入は、文字列のコピーが関与しないため、ポインタ上で動作し、より速くなります。

4
追加された