這裡介紹 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;
}
這樣的寫法適用於各種數值向量。
