[C++11] : auto,范围for循环,“{}“列表初始化,using
·
C++11 四大核心知识点详解
auto 自动类型推导
作用
编译器根据初始值自动推导变量类型,无需手动书写复杂类型,简化代码、提升可读性,C++11 正式标准化。
基本语法
auto 变量名 = 初始值;
基础用法
// 推导为 int
auto a = 10;
// 推导为 double
auto b = 3.14;
// 推导为 const char*
auto str = "hello";
// 推导为 std::string
auto s = std::string("c++11");
结合引用、const
auto默认舍弃引用、顶层 const,如需保留必须手动加修饰符
int x = 10;
int& ref = x;
const int cx = 20;
// 普通auto:推导为 int(丢弃引用)
auto v1 = ref;
// auto&:保留引用
auto& v2 = ref;
// const auto&:保留 const + 引用(常用,避免拷贝)
const auto& v3 = cx;
适用场景
- 复杂容器迭代器(最常用)
std::vector<int> vec = {1,2,3};
// C++11 前:std::vector<int>::iterator it
auto it = vec.begin();
- 模板返回值、长类型、lambda 接收等场景。
限制与注意事项
- 变量必须初始化:
auto a;编译报错,无初始值无法推导; - 不能用于函数形参、类非静态成员变量;
普通函数的形参类型是确定类型;
一旦用 auto,函数直接变成模板函数:
每传一种不同类型,编译器会实例化一份新函数
函数地址、重载决议、函数指针绑定全部改变 - 同一作用域下
auto变量推导类型固定,不能二次赋值不同类型。
范围 for 循环(基于范围的 for 循环)
作用
简化容器/数组遍历,无需手动管理迭代器、下标,C++11 新增语法。
标准语法
for (元素声明 : 可遍历对象)
{
循环体;
}
可遍历对象:数组、std::string、STL 容器(vector/map/list 等)。
基础遍历(值拷贝)
std::vector<int> vec = {1,2,3,4};
// elem 是容器元素的拷贝,修改不影响原容器
for (auto elem : vec)
{
std::cout << elem << " ";
elem += 1; // 仅修改副本
}
引用遍历(推荐,避免拷贝)
auto&:可读写原元素const auto&:只读遍历(性能最优,优先使用)
// 读写遍历
for (auto& elem : vec)
{
elem *= 2;
}
// 只读遍历(常量容器/仅读取场景)
const std::vector<int>& cv = vec;
for (const auto& elem : cv)
{
std::cout << elem << " ";
}
遍历原生数组
int arr[] = {10,20,30};
for (auto x : arr)
{
std::cout << x << " ";
}
注意事项
- 反汇编后范围 for 依赖迭代器,遍历过程中不要增删容器元素,会导致迭代器失效;
- 无法直接获取当前元素下标,需要下标时改用传统 for 循环;
- 仅支持完整遍历,不能指定起始/结束位置。
列表初始化(统一初始化语法)
C++11 统一 {} 初始化规则,称为列表初始化,解决 C++98 不同类型初始化语法混乱问题,又称大括号初始化。
基础语法
所有类型统一使用 {} 初始化,支持变量、数组、结构体、类、容器。
// 内置类型
int a{10};
double b{3.14};
// 数组
int arr[]{1,2,3};
int arr2[3]{10,20}; // 未赋值元素自动置0
窄转换检查(核心特性)
{} 会严格禁止隐式窄类型转换,编译报错,规避隐性 bug;() 无此限制。
int x1 = 3.9; // C++98 允许,截断为 3(隐患)
int x2(3.9); // 允许截断
int x3{3.9}; // C++11 编译报错:浮点转整型属于窄转换
容器初始化(极大简化代码)
STL 容器直接用 {} 初始化元素,C++98 无法实现:
// vector 初始化
std::vector<int> v{1,2,3,4};
// map 键值对初始化
std::map<int, std::string> m{{1,"a"}, {2,"b"}};
类/结构体初始化
普通结构体
struct Point
{
int x;
int y;
};
Point p{100, 200}; // 顺序赋值成员
自定义类
class Test
{
public:
Test(int a) : num(a){}
private:
int num;
};
Test t{666}; // 调用构造函数
初始化列表空值
{} 表示零初始化,内置类型初始化为 0,类调用默认构造:
int n{}; // n = 0
double d{}; // d = 0.0
类型别名 using
C++11 扩展 using 关键字,实现类型别名,替代传统 typedef,语法更直观、支持模板别名。
基础用法(替代 typedef)
语法对比:
typedef 原类型 别名;(C++98)using 别名 = 原类型;(C++11,推荐)
// 1. 普通类型别名
typedef unsigned int uint;
using UInt = unsigned int; // 等价,语法更自然
// 2. 容器类型别名(长类型简化)
typedef std::vector<std::string> StrVec;
using StringVec = std::vector<std::string>;
函数指针别名(typedef 易读性差,using 优势明显)
// C++98 typedef 写法(晦涩)
typedef void(*Func)(int, int);
// C++11 using 写法(直观:别名 = 原类型)
using FuncPtr = void(*)(int, int);
模板别名(using 独有能力,typedef 不支持)
这是 using 最大亮点,可以给模板起别名:
// 给 vector 模板起别名
template <typename T>
using Vec = std::vector<T>;
// 使用
Vec<int> v1;
Vec<std::string> v2;
结合 const、引用
using IntRef = int&;
using ConstStr = const std::string;
using 与 typedef 总结
- 功能等价:基础类型、指针、引用场景均可互换;
- 语法:
using 别名 = 类型阅读顺序和逻辑一致,更友好; - 关键区别:仅 using 支持模板别名,现代 C++ 优先使用
using。
更多推荐


所有评论(0)