21
#include <iostream>
#include <typeinfo>

int main()
{
    const char a[] = "hello world";
    const char * p = "hello world";
    auto x = "hello world";

    if (typeid(x) == typeid(a))
        std::cout << "It's an array!\n";

    else if (typeid(x) == typeid(p))
        std::cout << "It's a pointer!\n";   // this is printed

    else
        std::cout << "It's Superman!\n";
}

x文字列リテラルが実際には配列であるのに、ポインタであると推定されるのはなぜですか?

ナロー文字列リテラルの型は「n const charの配列」 [2.14.5 文字列リテラル [lex.string] §8]

4

3 に答える 3

25

この機能autoはテンプレート引数推定に基づいており、特に §14.8.2.1/2 (C++11 標準) に従って、テンプレート引数推定は同じように動作します。

  • P が参照型でない場合
    • A が配列型の場合、配列からポインターへの変換によって生成されたポインター型が、型推定のために A の代わりに使用されます。

x式の型を配列型にしたい場合は、&afterを追加するだけautoです:

auto& x = "Hello world!";

次に、autoプレースホルダーは と推定されますconst char[13]。これは、参照をパラメーターとして受け取る関数テンプレートにも似ています。混乱を避けるために: x の宣言された型は、配列への参照になります。

于 2012-08-18T08:09:01.480 に答える
6

文字列リテラルが実際には配列であるのに、なぜ x はポインターであると推定されるのですか?

配列からポインターへの変換のため。

xが配列として推定される場合は、次のことが許可されている場合のみ:

const char m[]          = "ABC";

const char n[sizeof(m)] = m; //error

C++ では、配列を別の配列で初期化することはできません (上記のように)。このような場合、ソース配列はポインター型に崩壊し、代わりにこれを行うことができます。

const char* n = m; //ok

型推論autoの規則は、関数テンプレートの型推論の規則と同じです。

template<typename T>
void f(T n);

f(m);     //T is deduced as const char*
f("ABC"); //T is deduced as const char*

auto n = m;     //n's type is inferred as const char*
auto n = "ABC"; //n's type is inferred as const char*

§7.1.6.4/6 は、auto指定子について次のように述べています。

変数 d に対して推定される型は、関数呼び出しからのテンプレート引数推定の規則を使用して決定される推定 A です (14.8.2.1) ...

于 2012-08-18T07:49:26.780 に答える