1.并发支持1.1内存模型C11引入了一个新的内存模型即C11内存模型C11 memory model。它定义了多线程并发环境下对共享数据的访问和修改行为以及对原子操作和同步操作的语义。在这些之上C11还提供了对原子类型和无锁编程的支持并且与之集成。C11内存模型确保了一些基本的原则原子性Atomicity对于原子类型std::atomic其成员函数的操作是原子的不会被其他线程中断。可见性Visibility对于非原子类型通过使用互斥量或同步操作来确保共享数据的可见性即在一个线程中对共享数据的修改会立即反映到其他线程中。有序性Ordering通过同步操作如互斥量、原子操作的memory_order参数等来定义操作的顺序性从而在多线程环境中确定操作和事件的相对顺序。1.2线程与锁C 对线程和锁级别编程的支持是 POSIX 和 Windows 所提供的线程和锁的类型安全变体 • thread——系统的执行线程支持 join() 和 detach() • mutex——系统的互斥锁支持 lock()、unlock() 和保证 unlock() 的 RAII 方式 • condition_variable——系统中线程间进行事件通信的条件变量 • thread_local——线程本地存储线程和锁模型需要使用某种形式的同步来避免竞争条件。C11 为此提供了标准 的 mutex互斥锁1.3期值futureC11 提供了• future——一个句柄通过它你可以从一个共享的单对象缓冲区中 get() 一个值可能需要等待某个 promise 将该值放入缓冲区。• promise——一个句柄通过它你可以将一个值 put() 到一个共享的单对象缓冲区可能会唤醒某个等待 future 的 thread。• packaged_task——一个类它使得设置一个函数在线程上异步执行变得容易由 future 来接受 promise 返回的结果。• async()——一个函数可以启动一个任务并在另一个 thread 上执行。2.简化使用2.1auto 和 decltypeC11中用auto关键字来支持自动类型推导。用decltype推导表达式类型。头文件#includetypeinfoauto让编译器在编译器就推导出变量的类型可以通过右边的类型推导出变量的类型。前提是定义一个变量时对其进行初始化代码语言javascriptAI代码解释auto a 10; // 10是int型可以自动推导出a是intdecltype用于推导表达式类型这里只用于编译器分析表达式的类型表达式实际不会进行运算。decltypde是不需要推导变量初始化的根据的是表达式对变量的类型就可以推导。代码语言javascriptAI代码解释auto varname value; decltype(exp) varname value; decltype(10.8) x; //x 被推导成了 double两者区别1auto用于变量的类型推导根据初始化表达式的类型来推导变量的类型常用于简化代码和处理复杂类型。而decltype则用于获取表达式的类型保留修饰符并且可以进行表达式求值。2auto在初始化时进行类型推导而decltype直接查询表达式的类型可以用于任何表达式包括没有初始化的变量。3auto在编译期间确定类型并且无法更改。而decltype在运行时才确定表达式的类型。4auto适用于简单的类型推导而decltype适用于复杂的类型推导和获取表达式的结果类型。2.2范围 for在C11中引入了范围for循环Range-based for loop它提供了一种简洁而直观的方式来遍历容器、数组、字符串和其他可迭代对象。代码语言javascriptAI代码解释for (auto element : container) { // 操作每个元素 }其中element是一个变量用于存储容器中的每个元素的值。container是一个可迭代对象例如数组、标准库容器或自定义容器。范围for循环的工作原理是它会自动遍历容器中的每个元素并将当前元素的值赋给element变量然后执行循环体中的代码块。循环体会针对容器中的每个元素执行一次。代码语言javascriptAI代码解释//实例 #include iostream #include vector int main() { std::vectorint numbers {1, 2, 3, 4, 5}; for (auto number : numbers) { std::cout number ; } return 0; }2.3资源管理指针在C11中引入了新的智能指针类用于更安全和方便地管理动态分配的资源避免内存泄漏和悬空指针等问题。以下是C11中的三种主要智能指针【1】std::unique_ptr1std::unique_ptr是一种独占式智能指针用于管理唯一的对象确保只有一个指针可以访问该对象。2使用std::unique_ptr可以自动释放动态分配的内存当指针超出作用域或被重置时它会自动删除所管理的对象。3通过std::make_unique函数可以创建std::unique_ptr对象如std::unique_ptrint ptr std::make_uniqueint(42);【2】std: :shared_ptr1std::shared_ptr是一种共享式智能指针多个指针可以同时共享对同一对象的拥有权。2std::shared_ptr使用引用计数技术追踪所管理对象的引用数量当引用计数变为零时自动销毁所管理的对象。3通过std::make_shared函数可以创建std::shared_ptr对象如std::shared_ptrint ptr std::make_sharedint(42);【3】std::weak_ptr1std::weak_ptr是一种弱引用智能指针它可以解决std::shared_ptr的循环引用问题。2std::weak_ptr指向std::shared_ptr管理的对象但不会增加引用计数。因此当所有std::shared_ptr对象超出作用域后即使还有std::weak_ptr对象存在所管理的对象也会被销毁。3通过std::shared_ptr的std::weak_ptr构造函数可以创建std::weak_ptr对象如std::weak_ptrint weakPtr sharedPtr;注意“它们的确智能但它们仍然是指针。”除非我们确实需要指针否则简单地使用局部变量会更好参考文章http://t.csdn.cn/CfDZr2.4统一初始化C11 引入了统一初始化Uniform Initialization语法这使得对象的初始化更加一致和简洁。使用统一初始化可以通过多种方式来初始化对象无论是基本类型、类类型还是数组都可以使用相同的语法。在 C11 中统一初始化有以下几种形式代码语言javascriptAI代码解释int x 42; // 直接初始化一个整数 std::string s(Hello); // 直接初始化一个字符串对象 int y x; // 使用拷贝初始化将 x 的值赋给 y std::vectorint v {1, 2, 3}; // 使用拷贝初始化进行向量初始化 int z{123}; // 使用列表初始化一个整数 std::vectorint nums{1, 2, 3}; // 使用列表初始化初始化一个向量 std::pairint, double p{42, 3.14}; // 使用列表初始化初始化一个键值对2.5nullptrnullptr是c11用来表示空指针新引入的常量值在c中如果表示空指针语义时建议使用nullptr而不要使用NULL因为NULL本质上是个int型的0其实不是个指针。举例代码语言javascriptAI代码解释void func(void *ptr) { cout func ptr endl; } void func(int i) { cout func i endl; } int main() { func(NULL); // 编译失败会产生二义性 func(nullptr); // 输出func ptr return 0; }2.6constexpr 函数constexpr 关键字的功能是使指定的常量表达式获得在程序编译阶段计算出结果的能力而不必等到程序运行阶段。C 11 标准中constexpr 可用于修饰普通变量、函数包括模板函数以及类的构造函数。常量表达式const experssion是指(1)值不会改变(2)在编译过程就能得到计算结果的表达式。constexpr和const的区别两者都代表可读const只表示read only的语义只保证了运行时不可以被修改但它修饰的仍然有可能是个动态变量而constexpr修饰的才是真正的常量它会在编译期间就会被计算出来整个运行过程中都不可以被改变constexpr可以用于修饰函数这个函数的返回值会尽可能在编译期间被计算出来当作一个常量但是如果编译期间此函数不能被计算出来那它就会当作一个普通函数被处理。