C++11之自動(dòng)類型推導(dǎo)的實(shí)現(xiàn)示例
一、auto 的基本概念
auto 是一個(gè)類型占位符,而非一個(gè)真正的類型。當(dāng)你用auto聲明變量時(shí),編譯器會(huì)根據(jù)變量的初始化表達(dá)式自動(dòng)推導(dǎo)出變量的實(shí)際類型,然后將auto替換為這個(gè)類型。
核心要求:用 auto 聲明的變量必須初始化,否則編譯器無(wú)法推導(dǎo)類型。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
// 1. 基本類型推導(dǎo)
auto a = 10; // 推導(dǎo)為 int
auto b = 3.14; // 推導(dǎo)為 double
auto c = 'A'; // 推導(dǎo)為 char
auto d = true; // 推導(dǎo)為 bool
auto e = "hello"; // 推導(dǎo)為 const char*(字符串字面量是const char[])
auto f = string("hi");// 推導(dǎo)為 std::string
// 驗(yàn)證推導(dǎo)結(jié)果(通過(guò)typeid查看類型)
cout << typeid(a).name() << endl; // 輸出:int(不同編譯器輸出可能略有差異,比如MSVC輸出int,GCC輸出i)
cout << typeid(e).name() << endl; // 輸出:const char*
// 2. 復(fù)雜類型推導(dǎo)(解決冗長(zhǎng)類型名問題)
vector<vector<int>> matrix = {{1,2}, {3,4}};
// 傳統(tǒng)寫法:vector<vector<int>>::iterator it = matrix.begin();
auto it = matrix.begin(); // 推導(dǎo)為 vector<vector<int>>::iterator
cout << (*it)[0] << endl; // 輸出:1
return 0;
}
執(zhí)行結(jié)果:
i
PKc
1
GCC/Clang 對(duì)復(fù)合類型的簡(jiǎn)寫規(guī)則:
P= Pointer(指針)K= const(Konst,德語(yǔ) “常量” 的縮寫,C++ 標(biāo)準(zhǔn)里用K表示 const)c= char所以PKc組合起來(lái)就是const char*(按順序:P (指針) + K (const) + c (char))
二、auto 的推導(dǎo)規(guī)則
auto的推導(dǎo)規(guī)則和模板參數(shù)推導(dǎo)基本一致,核心分三種情況:
規(guī)則 1:初始化表達(dá)式是普通類型(非引用、非指針)
auto會(huì)推導(dǎo)出和初始化表達(dá)式完全一致的類型(忽略頂層 const/volatile)。
#include <iostream>
using namespace std;
int main() {
const int x = 10;
auto y = x; // y的類型是int(頂層const被忽略)
y = 20; // 可以修改,證明y不是const
const auto z = x; // z的類型是const int(手動(dòng)加const,保留常量屬性)
// z = 30; // 編譯錯(cuò)誤:z是const int,不能修改
volatile int m = 20;
auto n = m; // n的類型是int(頂層volatile被忽略)
return 0;
}
規(guī)則 2:初始化表達(dá)式是引用 / 指針
- 如果表達(dá)式是引用,auto會(huì)推導(dǎo)出被引用的類型(忽略引用);
- 如果表達(dá)式是指針,auto會(huì)保留指針屬性;
- 如果是底層 const的指針 / 引用,auto會(huì)保留底層 const。
#include <iostream>
using namespace std;
int main() {
int val = 100;
int& ref_val = val;
auto a = ref_val; // a的類型是int(忽略引用)
a = 200;
cout << val << endl; // 輸出:100(a是拷貝,不影響val)
auto& b = ref_val; // b的類型是int&(手動(dòng)加&,保留引用)
b = 200;
cout << val << endl; // 輸出:200(b是引用,修改影響val)
const int c = 50;
const int& ref_c = c;
auto d = ref_c; // d的類型是int(忽略引用,頂層const也忽略)
auto& e = ref_c; // e的類型是const int&(保留底層const和引用)
// e = 60; // 編譯錯(cuò)誤:e指向const int
int* p = &val;
auto q = p; // q的類型是int*(保留指針)
const int* pc = &c;
auto r = pc; // r的類型是const int*(保留底層const的指針)
return 0;
}
規(guī)則 3:初始化表達(dá)式是數(shù)組 / 函數(shù)
- 數(shù)組名作為表達(dá)式時(shí),
auto會(huì)推導(dǎo)為指針類型; - 函數(shù)名作為表達(dá)式時(shí),
auto會(huì)推導(dǎo)為函數(shù)指針類型。
#include <iostream>
using namespace std;
void func() {
cout << "func called" << endl;
}
int main() {
int arr[5] = {1,2,3,4,5};
auto a = arr; // a的類型是int*(數(shù)組退化為指針)
cout << *(a+1) << endl; // 輸出:2
auto& b = arr; // b的類型是int (&)[5](數(shù)組的引用,保留數(shù)組類型)
cout << b[2] << endl; // 輸出:3
cout << sizeof(b) << endl; // 輸出:20(5個(gè)int,每個(gè)4字節(jié))
auto f = func; // f的類型是void (*)()(函數(shù)指針)
f(); // 調(diào)用func,輸出:func called
return 0;
}
三、auto 的核心使用場(chǎng)景
auto不是 “萬(wàn)能的”,但在以下場(chǎng)景能極大提升代碼可讀性和開發(fā)效率:
場(chǎng)景 1:簡(jiǎn)化冗長(zhǎng)的類型名
這是auto最核心的用途,尤其是 STL 容器的迭代器、函數(shù)返回值類型復(fù)雜的場(chǎng)景。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
// 復(fù)雜容器的迭代器
map<string, map<int, string>> complex_map;
complex_map["user1"][1001] = "Tom";
// 傳統(tǒng)寫法(冗長(zhǎng)且易出錯(cuò)):
// map<string, map<int, string>>::iterator it = complex_map.begin();
auto it = complex_map.begin(); // 簡(jiǎn)潔明了
cout << it->first << ": " << it->second[1001] << endl; // 輸出:user1: Tom
return 0;
}
場(chǎng)景 2:遍歷容器(配合范圍 for 循環(huán))
這是 C++11 后最常用的組合寫法,徹底擺脫手動(dòng)管理迭代器 / 索引。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {10,20,30,40};
// 只讀遍歷(拷貝)
for (auto val : nums) {
cout << val << " ";
}
cout << endl;
// 修改遍歷(引用)
for (auto& val : nums) {
val *= 2;
}
// 只讀遍歷(const引用,避免拷貝,效率更高)
for (const auto& val : nums) {
cout << val << " "; // 輸出:20 40 60 80
}
return 0;
}
場(chǎng)景 3:配合 Lambda 表達(dá)式
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {3,1,4,1,5,9};
// Lambda表達(dá)式的變量必須用auto聲明
auto compare = [](int a, int b) { return a > b; };
sort(nums.begin(), nums.end(), compare);
for (auto val : nums) {
cout << val << " "; // 輸出:9 5 4 3 1 1
}
return 0;
}
場(chǎng)景 4:處理模板類型
在模板編程中,auto可以簡(jiǎn)化模板參數(shù)推導(dǎo)后的類型聲明。
#include <iostream>
using namespace std;
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) { // C++11尾返回類型(配合auto)
return a + b;
}
int main() {
auto res1 = add(10, 20.5); // res1推導(dǎo)為double(10+20.5=30.5)
auto res2 = add(5, 3); // res2推導(dǎo)為int(5+3=8)
cout << res1 << " " << res2 << endl; // 輸出:30.5 8
return 0;
}
四、auto 的注意事項(xiàng)(避坑指南)
1. 必須初始化
auto是 “推導(dǎo)” 類型,沒有初始化值就無(wú)法推導(dǎo),編譯會(huì)報(bào)錯(cuò)。
// 錯(cuò)誤示例 auto x; // 編譯錯(cuò)誤:auto變量必須初始化 x = 10;
2. 不能用于函數(shù)參數(shù)
auto不能直接作為函數(shù)參數(shù)類型(C++14 支持auto作為函數(shù)返回值,但參數(shù)仍不支持)。
// 錯(cuò)誤示例
void func(auto x) { // 編譯錯(cuò)誤:參數(shù)不能用auto
cout << x << endl;
}
// 正確替代方案:用模板
template <typename T>
void func(T x) {
3. 不能用于數(shù)組聲明
auto不能直接聲明數(shù)組,但可以推導(dǎo)數(shù)組的引用或指針。
// 錯(cuò)誤示例
auto arr[5] = {1,2,3,4,5}; // 編譯錯(cuò)誤:auto不能聲明數(shù)組
// 正確寫法
int raw_arr[5] = {1,2,3,4,5};
auto* arr_ptr = raw_arr; // 推導(dǎo)為int*
auto& arr_ref = raw_arr; // 推導(dǎo)為int (&)[5]
4.推導(dǎo)可能 “丟失” const / 引用屬性
如前面的規(guī)則所述,auto默認(rèn)會(huì)忽略頂層 const 和引用,如需保留,需手動(dòng)加const/&。
int val = 10; const int& ref = val; auto a = ref; // a是int,丟失const和引用 const auto& b = ref;// b是const int&,保留屬性
5. 避免過(guò)度使用
auto能簡(jiǎn)化代碼,但過(guò)度使用會(huì)降低可讀性(比如簡(jiǎn)單類型也用 auto)。
// 不推薦(可讀性差) auto x = 10; // 直接寫int x = 10更清晰 // 推薦(類型冗長(zhǎng)) vector<map<int, string>> vec; auto it = vec.begin(); // 比寫完整迭代器類型更清晰
到此這篇關(guān)于C++11之自動(dòng)類型推導(dǎo)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C++11 自動(dòng)類型推導(dǎo)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++語(yǔ)言八大排序算法之桶排序全過(guò)程示例詳解
這篇文章主要為大家介紹了C/C++語(yǔ)言八大排序算法之桶排序算法過(guò)程的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11
opencv3/C++實(shí)現(xiàn)霍夫圓/直線檢測(cè)
今天小編就為大家分享一篇opencv3/C++實(shí)現(xiàn)霍夫圓/直線檢測(cè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
C語(yǔ)言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)實(shí)例講解單鏈表的實(shí)現(xiàn)
單鏈表是后面要學(xué)的雙鏈表以及循環(huán)鏈表的基礎(chǔ),要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C++,我們就要奠定好這塊基石!接下來(lái)就和我一起學(xué)習(xí)吧2022-03-03
內(nèi)核線程優(yōu)先級(jí)設(shè)置的方法介紹
本篇文章介紹了,內(nèi)核線程優(yōu)先級(jí)設(shè)置的方法。需要的朋友參考下2013-05-05
C++實(shí)現(xiàn)LeetCode(153.尋找旋轉(zhuǎn)有序數(shù)組的最小值)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(153.尋找旋轉(zhuǎn)有序數(shù)組的最小值),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++ Primer Plus 第四章之C++ Primer Plus復(fù)合類型學(xué)習(xí)筆記
數(shù)組(array)是一種數(shù)據(jù)格式,能夠存儲(chǔ)多個(gè)同類型的值。每個(gè)值都存儲(chǔ)在一個(gè)獨(dú)立的數(shù)組元素中,計(jì)算機(jī)在內(nèi)存中依次存儲(chǔ)數(shù)組的各個(gè)元素,今天給大家重點(diǎn)介紹C++ Primer Plus復(fù)合類型的實(shí)例詳解,感興趣的朋友一起看看吧2021-07-07

