6
#include <iostream>

using namespace std;

void swap(int *a, int *b) {
    *a = *a^*b;
    *b = *a^*b;
    *a = *a^*b;
}

int main()
{
    int array[]={1,9,2,8,3,7};
    for(int i=0; i<6; i++)
        cout<<array[i];
    cout<<endl;
    swap(array[1], array[4]);
    for(int i=0; i<6;i++)
        cout<<array[i];
    cout<<endl;
    return 0;
}

上記はテストサンプルです。を使用するswap(array[1], array[4]);と、配列内の2つの位置の値も交換されます。swap()しかし、関数には2つの整数値ではなく、2つのポインターが必要なので、これは私を混乱させます。

ご協力いただきありがとうございます:)

4

5 に答える 5

16
using namespace std;  

これがあなたの犯人です。名前空間をインポートするstd::と、その名前空間で宣言されているすべての識別子が取得されます。これには、が含まれる可能性がありますstd::swap

したがって、 (プログラムからではなく)呼び出しているstd::swap<int>(int&,int&)のは(標準ライブラリから)です。::swap(int*,int*)

物語の教訓:決して言わないでusing namespace std;ください。大きすぎます。

于 2013-01-24T19:43:49.387 に答える
7

それはあなた のを使用しませんswapが、std::swap

と呼んでみてください::swap(array[1], array[4]);。エラーが発生します。

using namespace std;これが悪い理由です。

于 2013-01-24T19:43:26.553 に答える
5

これが、避けるべき理由ですusing namespace std;

標準ヘッダーを含めると、の宣言がstd::swapプログラムにドラッグされたようです。そしてusing namespace std;それをグローバル名前空間にダンプしました。つまり、コードはバージョンではなく、それを呼び出しています。

于 2013-01-24T19:44:44.223 に答える
5

一時変数なしでこの問題を解決するための別の答えを提供しますか?

できないと思います。とにかく、「一時変数なし」という要件はどこから来るのでしょうか。一時変数によってコードが遅くなると思いますか?ここでこれが当てはまるかどうかを調べてみましょう。

展示物A:いくつかのハック。それがどのように機能するかはすぐにはわかりません。変数をそれ自体と正しく交換できません:

void swap1(int* a, int* b)
{
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}

生成されたアセンブリコード:

movl    (%rsi), %eax
xorl    (%rdi), %eax
movl    %eax, (%rdi)
xorl    (%rsi), %eax
movl    %eax, (%rsi)
xorl    %eax, (%rdi)

図表B:一時変数を使用した単純なコード。変数をそれ自体と正しく交換できます。

void swap2(int* a, int* b)
{
    int c = *a;
    *a = *b;
    *b = c;
}

生成されたアセンブリコード:

movl    (%rdi), %eax
movl    (%rsi), %edx
movl    %edx, (%rdi)
movl    %eax, (%rsi)

一時変数ソリューションは理解しやすく、すべてのケース処理し、コードを高速化します。

繰り返しますが、インタビューの状況以外では、xorトリックは完全に役に立ちません。そして、私が面接官であり、候補者がxorトリックを知っていたが、 「これはかわいいトリックですが、現実の世界では決して使用しませ」と言って資格を与えなかった場合、地獄は彼を雇わないでしょう。この答えを引用で締めくくりましょう。

明晰さは毎回賢さを打ち負かします。ラリー・オスターマン

于 2013-01-27T08:44:48.120 に答える
-1

あなたの問題は とは何の関係もありませんusing namespace std;。問題は、 int ( ) への左辺値参照をand でint&オーバーロードされた関数に渡していることです。using ディレクティブを削除すると、独自のスワップは呼び出されません。実際、C++ ではポインターから int への暗黙的な変換が許可されていないため、コードはコンパイルされません。関数を使用するには、次のように呼び出す必要があります。int&int*swap(&array[1], &array[4]);

ここで、これを反映するように関数呼び出しを修正すると、using ディレクティブの存在に関係なく機能するはずです。ただし、そうしないことをお勧めします。のセマンティクスは、ポインターではなく、 2 つの参照std::swapを交換することです。互換性のないセマンティクスで標準関数をオーバーロードすると、標準ライブラリに精通している人が混乱するだけでなく、onを使用する完全に有効なコードが壊れる可能性があります。std::swapint*

あなたは、「しかしusing namespace std;、それは彼らが決してすべきではない、彼らがそうである場合にのみ起こるだろう」と考えているかもしれません. ただし、信じられないかもしれませswapんが、これはまさにusing ディレクティブが必要な種類のアプリケーションです(もちろん、スコープは適切に設定されています)。この理由は、ユーザー コードがまさにあなたがしようとしていること、つまりアルゴリズムの特殊化を行う可能性があるためです。一部のライブラリ コードが単に. 代わりに、コードが次のようになっている場合swapstd::swap

template <typename T>
void foo (T& a, T& b)
{
    using std::swap; // Or simply namespace std;
    // ...
    swap (a, b);
    // ...
}

コンパイラは ADL を正しく採用し、特定の T (たとえば ) に対してユーザー定義のスワップを選択できますが、他の Tintには引き続き使用できます。std::swap

つまり、常に参照パラメーターをswap指定し、テンプレート化された型を交換する必要があるときはいつでも、スコープ付きの using 宣言を使用します。

于 2013-01-25T03:56:22.383 に答える