C++11的新特性

C++11引入了许多新特性,如更简单的初始化方式,增强了{}的使用,auto关键字,范围for循环,显式默认成员函数,final和override关键字,右值引用及其优化,线程支持和原子操作等,提高了编程效率和代码质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更加简单的初始化方式

C++11提供在类中定义类的数据成员,可以直接在成员之后添加=[缺省值],当通过编译器自动生成的默认构造函数初始化对象时,对应的数据成员就会被初始化成对应的缺省值

class Test
{
  public:
    int _t = 100;
};
int main()
{
    Test t;	//初始化完成后,t._t的值为100
    return 0;
}

更加强大的{}

在C++98中,数组可以使用{}来进行初始化,对自定义类型是不可以的

在C++11中,{}的使用范围变得更广,可以使用{}来初始化一个vector/list/string/map/set/multimap/multiset/unordered_map/unordered_set,在初始化时,可以添加=号,也可以不适用=号

int main()
{
    //c++11中,下面的方式是可以的
    std::vector<int> v1 = { 1,2,3 };
	std::vector<int> v2{ 1,2,3 };
	std::list<int> l1 = { 1,2,3 };
	std::list<int> l2{ 1,2,3 };
	std::string s1 = { "hello" };
	std::string s2{ "hello" };
	std::map<int, int> m1 = { {1,1}, {2,2}, {3,3} };
	std::map<int, int> m2{ {1,1}, {2,2}, {3,3} };
	std::set<int> set1 = { 1,2,3 };
	std::set<int> set2{ 1,2,3 };
	std::multimap<int, int> mt_map1 = { {1,1},{2,2},{3,3} };
	std::multimap<int, int> mt_map2{ {1,1},{2,2},{3,3} };
	std::multiset<int> mt_set1 = { 1,2,3 };
	std::multiset<int> mt_set2{ 1,2,3 };
	std::unordered_map<int, int> un_map1 = { {1,1}, {2,2}, {3,3} };
	std::unordered_map<int, int> un_map2{ {1,1}, {2,2}, {3,3} };
	std::unordered_set<int> un_set1 = { 1,2,3 };
	std::unordered_set<int> un_set2{ 1,2,3 };
    
    return 0;
}

注意:经过测试,stack和queue是不适用于该特性的

auto关键字

C++11中可以使用auto来表明该变量的类型由编译器在编译时期推导得出

注意:

  • 使用auto关键字必须进行初始化
  • 使用const/voliate关键字初始化auto类型变量时,编译器推导出的变量不具有const/voliate的限制

auto不能进行推导的场景

  • auto不能作为函数形参
  • auto不能定义为类的非静态成员变量
  • auto不能用来声明数组
  • 实例化模板时,不能使用auto来作为实例化的类型

范围for循环

C++11提供一种基于迭代器的语法糖遍历方式,它可以让程序员遍历一个有范围的容器时更加简单

int main()
{
    std::vector<int> v = {1,2,3};
    for(auto& e:v)
    {
        //这样即可遍历v中的每一个元素,e则就是元素的引用
    }
    return 0;
}

显式的缺省类的默认成员函数

当编写一个类想要使用编译器自动生成的默认成员函数时,只需要在函数的声明/定义时在函数的后面加上=default即可

class Test
{
  public:
  	Test() = default;
    Test& operator=(sonst Test& t);
};
Test& Test::operator=(sonst Test& t) = default;

完全删除某个默认成员函数

当编写代码的过程中想要完全删除某一个默认成员函数时,在该函数的声明后面加上=delete即可

class Test
{
  public:
    Test() = delete;
    Test& operator=(const Test& t) = delete;
};

注意:

  • =delete只能出现在函数的第一个声明中

final和override关键字

final关键字

  • final修饰虚函数,表示该虚函数不可以在派生类中进行重写。否则编译不通过。
  • final修饰类,表示该虚函数不可以再被继承。否则编译不通过。
class Test
{
  public:
    virtual void HelloWorld() final
    {
        //该函数不能在派生类中被重写,若重写,即报错
    }
};

class Test1 final
{
    //该类不能再被继承
  public:
  	Test1()
    {}
}

override关键字

该关键字用于基类虚函数,用来确保派生类中对继承自基类的虚函数进行了重写,若派生类没有进行重写,则就会编译报错

右值引用

右值引用的意义就在于消除了多种场景下进行的不必要的开销,例如接收函数返回值时进行的一次拷贝构造,右值引用可以看作是对该行为的一种优化方式

左值&右值

左值

  • 再赋值表达式中,出现在=左边的就是左值,而出现在=右边的不一定是右值
  • 可以取地址、有名字的就是左值,否则就是右值

右值:在C++11中右值由两个概念组成:纯右值&将亡值

  • 纯右值:纯右值是C++98中右值的概念,用于识别临时变量和一些不跟对象相关联的值
  • 将亡值:C++11新增跟右值引用相关的表达式,这些表达式通常是将要被移动的对象。例如:返回值右值引用T&&,std::move的返回值,转换为T&&的类型转换函数的返回值
std::string Test()
{
    std::string str("hello");
    return str;
}
int main()
{
    std::string&& str = Test();	//右值引用引用右值
    const std::string& str1 = Test();	//使用左值引用(普通引用)引用右值
    return 0;
}

std::move()

该接口的作用是将一个左值强制类型转换为右值引用,通过右值引用使用该值,实现移动语义

完美转发

在传递参数时,有时候可能会使参数的属性发生变化,完美转发即就是不改变参数的任何属性进行传参。

void func(const int n)
{}

int main()
{
    func(3);	//此处传递的参数为右值 但函数若进行接受就会将该参数变为左值
    func(std::forward(3));	//这样传递参数依旧是右值 但是右值要用const来接收
    return 0;
}

线程支持

C++11对线程进行了支持,在并发编程时不需要第三方库,直接使用标准库的<thread>头文件

原子操作

C++11引用了一系列原子操作,包含在标准库文件<atomic>中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值