引言

C++98 是 C++ 标准的第一个版本,而 C++11 及之后则带来了大量新特性和改进,它们在多个方面存在明显差异,需要进行学习

一 、auto自动类型推导

简而言之,auto可以自动推导数据类型

例子

1.推导数据类型

1
2
auto  i = 5; // int
auto str = "hello world" //const char*

2.推导返回值类型

1
2
3
auto sum(int a, int b) {
return a + b;
}

3.for循环

下面给出for循环三种方式,读者可以对比

1
2
3
4
5
6
7
map<string, int> mp;
mp["apple"] = 1;
mp["banana"] = 2;
mp["cherry"] = 3;
for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++) {
cout << (*it).first << endl;
}
1
2
3
for (auto it = mp.begin(); it != mp.end(); it++) {
cout << (*it).first << endl;
}
1
2
3
for (auto it : mp) {
cout << it.first << endl;
}

特殊情况

1.无法推导

1
2
auto i ;
i =5; // 报错,在第一行auto无法推导i的类型

2.理解复杂

假设一个程序中存在大量auto,程序员今天可能理解auto含义,明天可能就忘记了

二 、const_iterator常量迭代器

在 C++ 里,const_iterator 是一种特殊的迭代器,其作用是在遍历容器时保证不会修改容器内的元素

1
2
3
4
5
6
vector<int> vec = { 1,2,3,4,5 };
//vector<int>::iterator it = find(vec.begin(), vec.end(), 4);

vector<int>::const_iterator it = find(vec.begin(), vec.end(), 4);
vec.insert(it, 6); // 4之前插入6

在不需要修改元素的场景下,推荐使用 const_iterator 来增强代码的健壮性。

三 、noexcept抛出异常

作为异常规范​

用于声明函数​​不会抛出任何异常​​:

1
void func() noexcept; // 保证不抛出异常

编译器知道 noexcept函数不会抛出异常后,可以省略异常处理机制,提高运行效率

四 、tuple元组

1.创建元组

1
2
3
#include <iostream>
#include <tuple>
    auto student = make_tuple(3.8, 'A', "张三"); //创建元组

2.获取元素

1
2
3
4
    std::cout << "ID: 0, "<< "GPA: "
        << std::get<0>(student) << ", "
        << "成绩: " << std::get<1>(student) << ", "
        << "姓名: " << std::get<2>(student) << '\n';

3.修改元素

1
2
3
4
5
    std::get<0>(student) = 1.1;
    std::cout << "ID: 0, "
        << "GPA: " << std::get<0>(student) << ","
        << "成绩: " << std::get<1>(student) << ", "
        << "姓名: " << std::get<2>(student) << '\n';

注意
tuple可以修改元素,但不能添加元素,修改元素元素的类型应该相同

4.tie解包元组​

1
2
3
4
5
6
7
8
    double gpa;
    char grade;
    std::string name;
    std::tie(gpa, grade, name) = std::make_tuple(2.9, 'C', "李四");
    std::cout << "ID: 1, "
        << "GPA: " << gpa << ", "
        << "成绩: " << grade << ", "
        << "姓名: " << name << '\n';

五 、explicit禁止隐式类型转换

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
class A{
public:
    A(int x):num(x){}
//    explicit A(int x):num(x){}报错
    int num;
};
void fun(A a){}
int main() {
    A a = 10;
    cout<<a.num<<endl;
    return 0;

}

​STL 中为什么广泛使用 explicit?

  • 防止意外的隐式类型转换​
  • 避免歧义和代码可读性问题​

六 、mutable修改变量

const成员函数修改变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
class A{
public:
    void print() const{
        num++;
        cout<<"num的值为:"<<num<<endl;
    }
    mutable int num=0;
};
int main() {
    A a;
    a.print();
    return 0;

}

lambda修改变量

1
2
3
4
5
6
7

    int number =0;
    auto fun = [number]()mutable{
        number++;
        cout<<"number的值为:"<<number<<endl;
    };
    fun(); //number值传递,加上mutable可以修改

七 、decltype推导表达式类型​​

推导表达式类型

1
2
3
    int a = 1;
    decltype(a) b;
​​//借助a推导

结合auto

1
2
3
4
5
6
7
8
template<class T1,class T2>
auto add(T1 a,T2 b) ->decltype(a+b){
    return a+b;
}
int main() {
    auto ans = add(10,10);
    cout<<ans<<endl;
}

欢迎大家在评论区留言指正