1

次のコードでコンパイルエラーが発生しています。一時オブジェクトでもconst参照にバインドできると期待しています。だから私はそれが有効なコードであるべきだと思っています。ただし、g ++ではこのエラーが発生しますが、clangではこのようなエラーは発生しません。誰かが私にこれが起こる正確な理由を教えてくれますか?

#include <iostream>

struct TestClass
{
    TestClass() : str()
    {   
        strncpy(str, "hello", sizeof(str));
    }   

    char str[6];

    char (&getStr())[6]
    {   
        return str;
    }   
};

template <typename T>
void printFunc(const T& str)
{
    std::cout << str << std::endl;
}

int main()
{
    TestClass obj;
    printFunc(obj.str);
//  printFunc(TestClass().str);  // <- This line gives compilation error.
    printFunc(TestClass().getStr());
    return 0;
};
4

1 に答える 1

4

TestClass().strあなたのバージョンのGCCは、右辺値配列であるという事実につまずくと思います(C言語とC ++言語の両方でかなりエキゾチックなものです)。initailizerが右辺値である場合の参照初期化の詳細の何かが正しく実装されていません。どうやら、バグは後のバージョンで修正されました。

一方、とは両方ともobj.str左辺TestClass().getStr()配列です。これらは直接参照バインディングの単純なルールによって処理されるため、問題は発生しません。

コメントに対処するには:

関数テンプレートを次のように変更した場合

template <typename T> printFunc(const T str)

状況は劇的に変化します。今では、参照を拘束する問題ではなくなりました。これで、配列からポインタへの変換ルールが引き継がれます。

元のバージョンでは、タイプTはとして推定されましchar [6]たが、この新しいバージョンでは、タイプはとして推定されchar *ます。引数が関数に渡されると、配列型は完全に失われます。代わりに渡されるのはポインターです。これにより、参照バインディングの元の問題が完全に解消され、配列の左辺値または右辺値に関係なくコードがコンパイルされます。

たとえば、sizeof str関数内で印刷してみて、2つのバージョンの違いを観察できます。オリジナルは配列サイズをバイト(6)で出力し、新しいものはポインターサイズ(4ideoneのプラットフォーム用)を出力します。

于 2012-06-30T17:48:24.080 に答える