這裡介紹 C++ 語言的 auto 自動變數類型的用法,並提供幾種使用範例程式碼。

C++14 標準跟前一版的 C++11 比較起來沒有太大的變革,大概都是改善舊的語法,讓程式設計者更方便使用,這裡我將介紹 auto 這個 C++11 所新增的自動變數類型,以及在 C++14 中的變革。

auto自動變數類型

在 C++11 標準下,對於有被明確初始化的變數,我們可以使用 auto 這個新的變數類型,讓編譯器自動判斷其變數的類型,例如:

#include <cmath>
int main() {
  // 等同於 int x = 1;
  auto x = 1;
  // 等同於 double y = sin(1.3);
  auto y = sin(1.3);
  return 0;
}

使用 gcc 4.9 編譯 C++11 的程式碼時,要加上 -std=c++11

g++-4.9 -std=c++11 source.cpp

使用 gcc 6.3 編譯時就不需要加任何參數:

/usr/local/gcc-6.3.0/bin/g++ source.cpp

auto 變數實際的型別是在編譯時期進行判定的,在真正執行時就跟一般的 C++ 型別一樣,所以不會造成額外的負擔。

由於 auto 是根據變數的資料來判斷實際的型別,所以若是僅使用 auto 宣告變數,但未定義變數的內容,就會產生錯誤:

// 錯誤
auto z;

在 C++11 的標準中,auto 不可以用於函數的傳回值,但後來 C++14 的標準加入了這個用法:

// 在 C++11 中無法使用,但 C++14 則可以
auto my_fun() {
  int value = 3;
  return value;
}

int main() {
  my_fun();
  return 0;
}

編譯器會依照函數的傳回值來決定 auto 實際對應的變數型別。

而這段原始碼在編譯時就要使用 C++14 的標準才行,若用 gcc 4.9 編譯則必須加上 -std=c++14

g++-4.9 -std=c++14 source.cpp

而 gcc 6.3 則不需要任何參數:

/usr/local/gcc-6.3.0/bin/g++ source.cpp

C++98、C++11 與 C++14 範例比較

這是一段使用 C++98 標準的 C++ 程式碼,程式碼比較冗長:

#include <iostream>
#include <vector>

// 將每個數值加上 1
std::vector<int>& addOne(std::vector<int> &v) {
  for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    *it += 1;
  }
  return v;
}
int main() {
  // C++98 的 std::vector 初始化寫法
  static const int arr[] = {12, -3, 6, 19};
  std::vector<int> x (arr, arr + sizeof(arr) / sizeof(arr[0]) );
  std::vector<int> y = addOne(x);
  for (std::vector<int>::const_iterator i = y.begin(); i != y.end(); ++i) {
    std::cout << *i << ' ';
  }
  std::cout << std::endl;
  return 0;
}

整個程式的邏輯很簡單,一開始定義了一個 addOne 函數,它的作用就是把一個整數向量中的每個值都加 1,而主程式中我們定義了一個 x 向量,將其傳給 addOne 處理之後,指定給 y 向量,最後用一個迴圈將 y 輸出。

從 C++11 開始我們可以使用以範圍為基礎的 for 迴圈,加上 auto 語法後,可將程式碼改寫為:

#include <iostream>
#include <vector>
std::vector<int>& addOne(std::vector<int> &v) {
  for(auto& it : v) {
    it += 1;
  }
  return v;
}
int main() {
  // C++11 的 std::vector 初始化寫法
  std::vector<int> x = {12, -3, 6, 19};

  auto y = addOne(x);
  for (auto& it : y) {
    std::cout << it << ' ';
  }
  std::cout << std::endl;
  return 0;
}

而在 C++14 之後,函數的傳回值也可以使用 auto

auto& addOne(std::vector<int> &v) {
  for(auto& it : v) {
    it += 1;
  }
  return v;
}

g++ 4.9.1 以後的編譯器甚至還有支援這種泛型函數(generic function)的寫法:

auto& addOne(auto &v) {
  for(auto& it : v) {
    it += 1;
  }
  return v;
}

這樣的寫法適用於各種數值向量。

參考資料:Solarian ProgrammerStackOverflow