1

以下のコードではコンパイル エラーが発生しますが、何が間違っているのかわかりません。このようなばかげた質問をして申し訳ありません。

$ cat swapcstrings.cc
#include <iostream>

void swap(char*& c, char*& d) {
    char* temp = c;
    c = d;
    d = temp;
}

int main() {
    char c[] = "abcdef";
    char d[] = "ghijkl";
    std::cout << "[" << c << "," << d << "]\n";
    swap(c, d);
    std::cout << "[" << c << "," << d << "]\n";
}
$ g++ swapcstrings.cc
swapcstrings.cc: In function ‘int main()’:
swapcstrings.cc:13: error: invalid initialization of non-const reference of type ‘char*&’ from a temporary of type ‘char*’
swapcstrings.cc:3: error: in passing argument 1 of ‘void swap(char*&, char*&)’
$
4

2 に答える 2

8

配列は変更できず、一時的なポインターに崩壊するだけであり、実際にはポインターではなく、スワップすることはできません。配列のアドレスを変更することはできず、配列から取得した一時ポインターを非const参照にバインドしようとするとコンパイラ エラーが発生します。これは言語の規則に反します。

配列を宣言してから、それらへの 2 つのポインターを交換します。

char a[] = "abcdef";
char b[] = "defghi";

char* aptr = a, *bptr = b;

std::cout << "[" << aptr << "," << bptr << "]\n";
swap(aptr, bptr);
std::cout << "[" << aptr << "," << bptr << "]\n";

または、関数のプロトタイプを変更できる場合const char*は、最初に次を使用します。

void swap(const char*& c, const char*& d) {
    const char* temp = c;
    c = d;
    d = temp;
}

const char* c = "abcdef", // These must be const char* because the arrays are
          * d = "ghijkl"; // const char[N]

std::cout << "[" << c << "," << d << "]\n";
swap(c, d);
std::cout << "[" << c << "," << d << "]\n";
于 2012-10-07T18:55:57.327 に答える
3

cおよびdは配列です。それらは、ポインターが必要な場所でポインターに自動変換されます。これは、コンパイラの出力が示す「一時的な」ものです。次のように考えてください。

char c[] = "abcdef", d[] = "ghijkl";
char *cp = (char*)c, *dp = (char*)d;
swap(cp, dp);

上記はコンパイルされますが、元の and ではなく、 and のみが交換cpdpcますd。上記のコードはこれらのポインターに名前を付けているので、それらへの参照もできるようになりました。しかし、元のコードでは、一時変数に名前がなく、一時変数を変更するとエラーが発生する可能性がありました。したがって、コンパイラはそれを許可せず、代わりに文句を言います。

配列内の C スタイルの文字列を交換する場合は、一度に 1 文字ずつ交換する必要があります。

template<size_t n> void swap(char (&a)[n], char (&b)[n]) {
  for (size_t i = 0; i != n; ++i)
    std::swap(a[i], b[i]);
}

このテンプレートは、両方の引数が同じ長さの配列であることを保証します。

于 2012-10-07T18:59:22.640 に答える