2015-11-13 7 views
45

autoを使用してポインタ型を推測すると、私は奇妙な現象を発見しました。私のコードは次のようである:C++でのautoの使用11

#include <iostream> 
using namespace std; 
int main() 
{ 
    int i = 100; 
    auto p1 = &i; 
    auto *p2 = &i; 

    cout << *p1 << " " << *p2 << endl; 

    return 0; 
} 

コンパイルして実行した後、我々は*p1*p2の結果が同じであることを見つけることができ、両方これはp1p2の両方intを指すポインタ・オブジェクトであることを意味100オブジェクト。

[[email protected] ~]$ ./test 
100 100 

p1p2を定義し、これらの二つの文の間に違いはありますか? template argument deductionで使用される変数の宣言に使用

+9

もちろん、他に何が起こる可能性がありますか? p1とp2が両方のポインタでない場合、それらを '&i'で初期化できませんでした。'p2'がポインター型の変数であることを明確にするために、' auto * p2'ではなく 'auto * p2'という言葉で書くべきではないかと思うかもしれませんが、ポインティングされた型はコンパイラーによって自動的に演繹されます。 –

+1

'auto * p2 = init()'は生ポインタ型を強制します。例えば、いつも 'init()'が 'shared_ptr 'を返すようにリファクタリングされ、この値をコピーしてメモリに保存する代わりに、コンパイルエラーが発生し、 'shared_ptr '、 'weak_ptr '、または' T& '。 – jingyu9575

+1

これは、 'auto'が魔法であり、潜在的に混乱する理由です。 –

答えて

19

auto指定子は、同じ規則で、その種類 を推定します。

最初の例を考えてみましょう(つまり、auto p1 = &i;)。次のように auto指定子のタイプが推定される:

  1. autoは虚数型テンプレートパラメータに置き換えられる(例えば、U p1 = &i;)。
  2. &iタイプはint*であり、従って驚きはなく、テンプレート控除ルールによればUint*に推定される。

次に、2番目の例(つまり、auto *p2 = &i)について考えてみましょう。

  1. また、autoは、虚偽のテンプレートパラメータ(例えば、U* p1 = &i;)に置き換えられます。
  2. &iタイプはint*であり、テンプレート控除ルールに従ってUintに推定されます。このよう

auto *p2 = &i;にプレースホルダタイプautoは正しく、あなたが期待している可能性があるとして、タイプint**p2ビーイングにつながること、intとしてではなくint*と推測されます。

+2

+1テンプレート引数の減算ルールに言及してください。しかし、メモのように、「auto」型の控除はテンプレート型の控除とは少し違いがあります(MeyersのEffective Modern C++を参照)。詳細は覚えていませんが。 –

+3

違いは中括弧イニシャライザのリストによるものです:auto x = {1,2,3}。 Scott Meyersの書籍(Effective modern C++)から引用されています: "オートタイプの控除は通常テンプレートタイプの控除と同じですが、オートタイプの控除では括弧付きのイニシャライザがstd :: initializer_listを表し、テンプレートタイプの控除は行わないと仮定しています。 – spraetor

84

差は、第二の場合に自動intを推定しなが​​ら第一の場合にはオートがタイプint*の両方p1p2ビーイングをもたらす、int*に推定されることです。 autoの型減算機構は、テンプレート引数の型減算機構と同等です。あなたの例では型推論は、したがって、両方の機能がvoid型(int型*)としてインスタンス化される

template<typename T> 
void foo(T p1); 

template<typename T> 
void bar(T* p2); 

int main() 
{ 
    int i; 
    foo(&i); 
    bar(&i); 
} 

に似ていますが、後者の場合Tintを入力している間、最初のケースでTint*に推測されています。

+8

は、同等のテンプレートのインスタンシエーションをレイアウトするためにアップリストされました –

関連する問題