SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Modern C++入門

データ型は明示しないで! Modern C++での型推論

第2回 変数の型はautoで!

  • このエントリーをはてなブックマークに追加

ダウンロード sample.zip (2.2 KB)

 本連載では、Modern C++と称されるC++について、Modern C++らしい言語仕様をピックアップし紹介していきます。第2回は、第1回で「データ型は明示しないで!」で触れた型推論を紹介します。C/C++は静的な型付けを行うプログラミング言語ですが、型推論によって型の宣言はどう変わるのか?を中心に見ていきます。

  • このエントリーをはてなブックマークに追加

はじめに

 C言語から派生したオブジェクト指向プログラミング言語であるC++は、21世紀に入ってまったく別物とも言えるプログラミング言語に成長していきました。それは、Modern C++と称されています。1990年代にC++を触っていたプログラマが現在の仕様を知れば、隔世感に苛まれるのではないでしょうか。本連載では、かつてはC++をたしなんでいたという方、今からC++言語を始めるという方に向けて、Modern C++らしい言語仕様をピックアップし紹介していくことで、今のC++言語の姿を理解していただきます。

対象読者

  • かつてはC++をたしなんでいたという方
  • 今からC++言語を始めるという方
  • モダンなプログラミング言語のパラダイムに興味のある方

必要な環境

 本記事のサンプルコードは、以下の環境で動作を確認しています。

  • macOS Monterey/Windows 10(64bit)
    • Xcode Command Line Tools 2395
    • MinGW GCC 9.2.0

型推論って何?

 少々間が空いてしまいましたが、20世紀のC++プログラマ(筆者)が、今(21世紀)のC++を知って驚く連載の第2回です。今回は、型推論(Type Inference)です。第1回では、「データ型は明示しないで!」と、C言語から慣れ親しんだ構文を一気に否定するようなことが書かれていましたが、それを納得感のあるように紹介するのが今回の目的です。

なぜ静的な型付けが必要なのか

 改めて言うまでもなく、C++は静的な型付けを行うプログラミング言語です。つまり、コンパイルの時点で型が明確である必要があります。静的型付けのプログラミング言語では、コンパイルによって実行環境ネイティブなコード(要するに機械語かそれに準ずるもの)を生成する必要があるので、データの型すなわちメモリ上に占める領域の大きさと、それを取り扱う命令は明らかである必要があります。このようなことで、「int a;」と書いて32ビットのメモリ領域を必要とする、符号付き整数の命令を使う、などと決めるわけです。

何度も書くと間違いの元となる

 「int a;」のような単純な宣言文なら、何度書こうがさして苦にはなりません。しかし、後述するテンプレート機能を使ったライブラリでは、異なる名前空間にあったり型パラメータを伴ったりするので、型名が長くなりがちで、さらにこういう型に限って、ソースコード中に何度も現れたりするものです。例えば、リスト的なデータ構造であるベクタ(std::vector)ではこんな感じです。

リスト auto_summary.cpp
std::vector<int> vec{1, 2, 3};	(1)
for(std::vector<int>::iterator itr = vec.begin(); itr != vec.end(); itr++) {	(2)
    cout << *itr << endl;
}

 このように、(1)(2)と「vector<int>」を2回も書かなければなりません。特に(2)では、右辺の型は分かっているんだから、左辺はそれに合わせてよ! という文句が出そうです。

初期化漏れを防止する

 このように、同じ意味の型を何回も書くのはかったるいな! というときに型推論は役立つわけですが、もっと切実な理由があります。それは、変数の初期化漏れの防止です。JavaでもRustでもそうなんですが、変数は宣言しっぱなしでOKです。宣言しっぱなしというのは、明確な初期化が行われていないという意味です。こうなると、その変数を参照しようとするといろいろとまずいことが起きてきます。

  • 基本データ型とかなら、どんな値か分からない
  • ポインタ型とかなら、どこを指しているか分からない(ダングリングポインタ)

 なので、実行時にプログラムが不可解な動作をしたり、いきなり落ちたりするわけです。しかし、コンパイラはどんどん進化しているので、初期化されていない変数を参照しようとすると警告を発したり、Rustのようにエラーとしてしまうこともできます。このように初期化漏れによる事故は限りなく低くなっていますが、できればゼロにしたいところです。

型推論の登場

 そのようなわけで型推論です。型推論では、推論の根拠となるもの、ほとんどの場合は初期化子を解析し、適当と思われるデータ型を自動的に割り当てます。

auto x = 10;

 何とautoです。どこかで見覚えがあるような……と思った方は、次の[NOTE]をご覧になってください。自動を意味するautoを指定することで、型はよくわからないけど、とにかく変数を宣言するぜ! というわけです。それにしてもautoかぁ、と思ったのは筆者だけでしょうか。C#やJavaなんかも今では型推論を使えるようになっていて、var(変数の意)で始めているのになぁ……(Rustなんかではletを使っているようですけど)。JavaScriptっぽく見えるのを嫌ったのでしょうか。

 それはさておき型推論では、根拠すなわち初期化式が必要なので、初期化漏れを防ぐことができます。上記を「auto x;」とだけ書いても、初期化式がないので型を推論する根拠がありません。つまり宣言しっぱなしを防ぐことができます。これはつまり、プログラムの安全性が向上するということです。

 このようなメリットを感じていただけたところで、詳細に切り込んでいきましょう。ただし、一口に型推論と言っても仕様は膨大なので、基本的な部分を取り上げています。「型推論」ってこんな感じなんだ、というところを感じ取ってくださいね。

[NOTE]auto宣言子

 auto宣言子は、C++11で型推論に使われるようになるまでは、自動変数の宣言に使われていました。自動変数とは、スタック上に確保される変数のことで、いわゆるローカル変数、局所変数と呼ばれるものが該当します。「auto int a;」のように宣言します。autoは既定であり、実際には自動変数の宣言にautoが用いられることはほとんどなく、単に「int a;」というようにautoは省略されていました。筆者も、ほとんどautoを書いたことはありません。

 ちなみに、auto宣言子はレジスタ変数のためのregister宣言子に対するものですが、register宣言子もコンパイラの最適化技術の向上とともに用いられなくなりました。優先してレジスタに割り当てるべき変数を、コンパイラが自動的に決定するからです。

[NOTE]C++プログラムのコンパイル

 以降のサンプルは、基本的に「gcc -o 出力先ファイル名 ソースファイル名」でコンパイルできますが、環境によってはライブラリやC++バージョンの指定が必要になることがあります。コンパイルやリンクでエラーが発生するときには、以下のようにライブラリの指定(-lstdc++)、C++バージョンの指定(-std=c++11)の追加を検討してください。

% gcc -o sample sample.cpp -lstdc++ -std=c++11	// c++14, c++17, c++20など

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
変数の型推論

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
Modern C++入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook <個人紹介> WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/18109 2023/08/17 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング