したがってvar
、コンパイラで派生した匿名型があるため、C# での使用は理にかなっていることを理解しています。C++ にはこの機能がないようです (私が間違っていない限り)。では、auto
キーワードを指定する意味は何ですか?
(C# とは異なりauto
、メンバー/グローバル変数に対して機能するのはちょっとクールです。これはクールだと思いますが、その存在を正当化するのに十分ではないようです)。
auto
汎用プログラミングと、プログラマーのタイピングの節約の両方に関して、多くの用途があります。
たとえば、これを考えてみましょう。次のように入力しますか?
std::unique_ptr<name::long_type::goes_here> g =
std::make_unique<name::long_type::goes_here>(1,2,3,4)
また:
auto g = std::make_unique<name::long_type::goes_here>(1,2,3,4)
はい、どちらも長いですが、戻り値の型はわかっているので、再度指定するのは少し面倒です。これはイテレータにも当てはまります。
for(auto i = vec.begin(); ...)
対:
for(std::vector<type>::iterator i = vev.begin(); ...)
汎用プログラミングでの使用は、関数の戻り値の型を把握するため、または型がわからない汎用アルゴリズムを実行している場合にも使用されます。
たとえば、非常に基本的な例を考えてみましょう。
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
これにより、コンパイラーは、私たちが自分でそれを理解しようとするのではなく、追加操作のタイプを把握することができます。C++14 では、末尾の戻り値の型を省略できることに注意してください。汎用プログラミングでのその使用は、それだけにとどまりません。アルゴリズムのラッパー関数として任意のタイプのコンテナを操作したい場合はauto
、それを支援するために使用できます。例えば:
template<class Cont>
void my_sort(Cont&& cont) {
using std::begin;
auto first = begin(std::forward<Cont>(cont));
// work with the iterators here
}
将来 (C++14)、 auto を使用して、次のようなポリモーフィック ラムダを作成できます。
[](auto a) { return a + 4; }
これも便利です。
auto
C++には多くの用途があります
匿名関数オブジェクト、別名クロージャー、別名ラムダ インスタンス。 auto
それらを保存する唯一の方法です。これらの型から派生した型を生成することもできます。
C++ は、カスタム アロケーターとハッシュ関数を使用する順不同マップへの非ミューテーション イテレーターの型など、非常に複雑な型を持つことができます。 typedef
はこれを軽減できますがm.begin()
、特定の名前を持つ a の型はそれほど有益ではありfoo_iterator it =
ません。auto foo_iterator =
auto
戻り値の型推定では、大量のトレイト ボイラープレートを使用せずにauto
一部の機能を実行するために必要なキーワードを使用します。template
ボイラープレートを排除することは共通のテーマです。C++ の堅牢な型システムは、型が多くの情報を運ぶことができることを意味し、使用するたびにそれをエンコードすることは逆効果になる可能性があります。
一部のダックタイプtemplate
コードでは、変数の型を推測する作業は、変数の値をコーディングする作業とほぼ同じであり、構造もほぼ同じですdecltype(long expression) x = long expression;
。 auto
その重複を排除します。
最後に、C++1y では、型推定ラムダを使用auto
して、引数が推定されたものであると言います。軽量の並べ替えtemplate
。これを非ラムダに拡張する話もスカンクワークスにあります。
これは、auto を使用できなかった実際の例です。
戻り値の型が実装固有であり、簡単に宣言できない C++ で switch 型ステートメントを実行しようとしていました。したがって、「auto」を使用することは、マップ宣言の型ルックアップを解決するためのおそらく正しい方法です。
auto foo = boost::bind(&VegaFactory::load_commodity_one_leg,this,conn,_1);
std::map<std::string,decltype(foo)> methods;
methods.insert(std::make_pair("FOO",commodityOneLeg));
auto f = methods.find(bar);
// Call f here
C++ には「匿名」型があります。名前を使用できないため、名前で参照できない型です。これは、C++11 とラムダの前でも当てはまりました。次のコードを検討してください。
class foo {
class bar {
public:
void baz() { }
};
public:
static bar func() { return bar(); }
};
foo::func().baz(); // OK, only the name "bar" is private
??? a = foo::func(); // Umm...
auto b = foo::func(); b.baz(); // Hooray!
プライベート スコープで実際に宣言されていなくても、ライブラリがその API でいくつかの型を未指定のままにしておくと便利なことがよくあります。特に、ネストされたすべてのテンプレート引数で型名が任意に長くなる式テンプレートやその他のテンプレート メタプログラミングを多用する場合は特にそうです。 . 標準自体でさえこれを行います-たとえば、結果の型はstd::bind
仕様で定義されていません。
シンタックスシュガー
むしろ言う
auto i = mapping.begin();
以上
std::map<int, int>::iterator i = mapping.begin();
Herb Sutter の記事「Almost Always Autoauto
」を読むと、明示的な型よりも使用する価値がある理由の素晴らしい例が得られます。主な利点は、タイピングの削減であり、基になる型が変更された場合の安全性が向上します。ただし、私のお気に入りの例の 1 つは、重複を減らす方法についてです。スタックに割り当てる場合は、次を使用します。
MyClass c(param);
ただし、ヒープ上に作成する場合は、次のものが必要です。
MyClass* c=new MyClass(param);
したがって、を複製する必要がありましたMyClass
が、RHS は既に変数をMyClass
ポインターに強制しているため、代わりにこれを使用できます。
auto c=new MyClass(param);
として宣言する場合はunique_ptr
、以前は次のものが必要でした。
unique_ptr<MyClass> c=make_unique<MyClass>(param);
これは次のように省略できます。
auto c=make_unique<MyClass>(param);