C/C++教程

C++11特性小结

本文主要是介绍C++11特性小结,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、关键字

  (1)新增关键字:thread_local、static_assert、nullptr、noexcept、decltype、constexpr、char32_t、char16_t、alignof、alignas

    thread_local:实现了线程局部存储,让每个线程都独立访问数据,互不干扰;thread_local 标记的变量在每个线程里都会有一个独立的副本,是线程独占的,所以就不会有竞争读写的问题。

    static_assert:静态断言,它只在编译时生效,运行阶段看不见,所以是“静态”的;

    decltype:自动类型推导,不仅能够推导出值类型,还能够推导出引用类型,也就是表达式的“原始类型”,而auto只能在初始化时自动推导类型

  (2)修改关键字:auto、class、default、delete

    auto:根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype;

    default:明确告诉编译器,使用默认实现,编译器会为其自动生成默认的函数定义体,只需在函数声明后加上=default;

        class DemoClass
        {
        public:
            DemoClass() = default;//明确告诉编译器,使用默认实现
            ~DemoClass() = default;
        }

    delete:明确地禁用某个函数,在成员函数声明后加 = delete,delete 关键字可用于任何函数,不仅仅局限于类成员函数; 

        class  DemoClass
        {
            .........

            public:
              DemoClass(const DemoClass&) = delete;//禁止拷贝构造
              DemoClass& operator = (const DemoClass&) = delete;//禁止拷贝赋值
        }

    final:可以显式地禁用继承,防止其它人有意或者无意地产生派生类,如:

    class DemoClass final {
        .....
    }

 

二、新语法

  (1)constexpr变量:将变量声明为constexpr类型以便由编译器来验证变量是否是一个常量表达式,比const更强的约束,这样可以得到更好的效率和安全性;

  (2)内存对齐支持:alignof基本值对齐,每个元素的起始地址必须是其中一个元素最大长度的整数倍;alignas指定对象的对齐字节数,再使用alignof来查看

  (3)nullptr:用于标识空指针,它可以转换成任何指针类型和bool布尔类型

  (4)random_device 随机数生成器

  (5)std::ref和std::cref

  (6)强枚举类型(strong-type enum)

  (7)lamda表达式

    [=]:值捕获,捕获外部作用域中所有变量,并作为副本在函数体中使用;

    [&]:引用捕获,捕获外部作用域中所有变量,并作为引用在函数体中使用。

  (8)POD

  (9)显式转换操作

  (10)初始化列表std::initializer_list

  (11)类型推导auto、decltype

  (12)static_assert静态断言

  (13)声明:不可见enum声明、属性声明、空声明(;)、long long类型

  (14)预处理:_Pragma运算

  (15)表达式:alignof查询类型的对齐要求、用户定义字面量

  (16)原始字符串R"(a string)"

  (17)新的for循环:for(x:range)

    //遍历字符串
    std::string str = “hello, world”;
    for(auto ch : str)
    {
        std::cout << ch << std::endl;
    }
    //遍历str,输出每个字符,同时用上auto,简直是如虎添翼。(auto也是c++11的新特性)

    //遍历数组
    int arr[] = {1, 2, 3, 4};
    for(auto i : arr)
    {
        std::cout<< i << std::endl;
    }
    //不用知道数组容器的大小,即可方便的遍历数组。

    //遍历stl 容器
    std::vector<std::string> str_vec = {“i”, “like”,  "google”};
    for(auto& it : str_vec)
    {
        it = “c++”;
    }
    //在这段程序中,可以返回引用值,通过引用可以修改容器内容。

    //遍历stl map 
    std::map<int, std::string> hash_map = {{1, “c++”}, {2, “java”}, {3, “python”}};
    for(auto it : hash_map)
    {
        std::cout << it.first << “\t” << it.second << std::endl;
    }
    //遍历map返回的是pair变量,不是迭代器。

  (18)数字限制numeric_limits

  (19)追踪返回类型语法

  (20)内联名字空间  inline namespace

  (21)非受限联合体

  (22)扩展的整形

  (23)扩展的friend语法,可以把一些函数或类声明为“友元”,函数或类就成为该类的友元函数,在友元函数或友元类内部就可以访问该类对象的私有成员

class CCar
{
private:
    int price;
    friend class CDriver;  //声明 CDriver 为友元类
};
class CDriver
{
public:
    CCar myCar;
    void ModifyCar()  //改装汽车
    {
        myCar.price += 1000;  //因CDriver是CCar的友元类,故此处可以访问其私有成员
    }
};

三、STL容器

  (1)std::array

  (2)std::forward_list单向链表

  (3)无序容器:std::unordered_map/std::unordered_multimap、std::unordered_set/std::unordered_multiset

  (4)std::tuple元组:std::make_tuple、std::get、std::tie

  (5)std::begin/std::end迭代器

  (6)std::move

  (7)hash

  (8)emplace

四、线程

   (1)std::thread

  (2)std::mutex

  (3)std::lock

      std::lock_guard 在构造函数中进行加锁,析构函数中进行自动解锁

      std::unique_lock 是通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用

      unique_lock比lock_guard使用更加灵活,功能更加强大,可临时解锁和再上锁,而不必等到析构时自动解锁

  (4)std::call_once

  (5)std::atomic

  (6)std::condition_variable

      wait()、notify_one()、notify_all()

  (7)async

  (8)volatile

  (9)std::future

  (10)std::thread_local

 

五、正则表达式

   std::regex正则表达式:basic_regex、sub_match、match_results

六、智能指针

   (1)std::share_ptr

    std::shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。再最后一个shared_ptr析构的时候,内存才会被释放。

    shared_ptr不能通过“原始指针直接赋值”来初始化,需要通过构造函数和辅助方法来初始化

    不要在函数实参中创建shared_ptr,函数参数的计算顺序在不同的编译器不同的约定下可能是不一样的,一般是从右到左,但也可能从左到右,容易出现内存泄漏

    通过shared_from_this()返回this指针

  (2)std::unique_ptr

    unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr

  (3)std::weak_ptr

七、函数

   (1)std::function

//1.保存普通函数
void printA(int a)
{
cout << a << endl;
}
std::function<void(int a)> func;
func = printA;
func(2); //2

//2.保存lambda表达式
std::function<void()> func_1 = [](){cout << "hello world" << endl;};
func_1(); //hello world

//3.保存成员函数
class Foo{
Foo(int num) : num_(num){}
void print_add(int i) const {cout << num_ + i << endl;}
int num_;
};

std::function<void(const Foo&,int)> f_add_display = &Foo::print_add;
Foo foo(2);
f_add_display(foo,1);

  (2)std::bind

//可将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。


void fun_1(int x,int y,int z)
{
cout<<"print: x=" <<x<<",y="<< y << ",z=" <<z<<endl;
}

void fun_2(int &a,int &b)
{
a++;
b++;
cout<<"print: a=" <<a<<",b="<<b<<endl;
}

int main(int argc, char * argv[])
{
//f1的类型为 function<void(int, int, int)>
auto f1 = std::bind(fun_1,1,2,3); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
f1(); //print: x=1,y=2,z=3

auto f2 = std::bind(fun_1, placeholders::_1,placeholders::_2,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f2 的第一,二个参数指定
f2(1,2);//print: x=1,y=2,z=3

auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f3 的第二,一个参数指定
//注意: f2 和 f3 的区别。
f3(1,2);//print: x=2,y=1,z=3

}

  (3)std::bad_function_call

  (4)mem_fn

 

八、类

   (1)类型别名

      使用using起别名;

  (2)类成员初始化

  (3)类中函数:仿函数(func)、委托构造函数、继承构造函数、移动构造函数、移动赋值运算符、并行动态初始化和析构

     仿函数:它是个类,重载了()运算符;

     委托构造函数:一个构造函数直接调用另一个构造函数,把构造工作“委托”出去;

    继承构造函数:用using来声明继承基类的构造函数;

    移动构造函数:构造函数的参数有两个&操作符, 接收的是“右值引用”的参数;对于指针,拷贝构造函数使用深拷贝,移动构造函数使用浅拷贝,拷贝构造函数的参数是一个左值引用,移动构造函数的初值是一个右值引用;

 

九、模板

 

十、性能

  (1)右值引用

  (2)std::move

  (3)std::forward

  (4)原子操作:atomic_bool、atomic_int

 

这篇关于C++11特性小结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!