Skip to content

C++11

线程库

C++11中提供了一个多线程库,它可以让程序员在C++代码中创建和管理多线程。这个库包含了许多类和函数,可以用来操作线程、互斥量、条件变量和其他的同步对象。

下面是一个简单的C++11多线程程序的例子,它创建了两个线程,分别打印"hello"和"world":

cpp
#include <iostream>
#include <thread>

int main() {
  std::thread t1([]() { std::cout << "hello" << std::endl; });
  std::thread t2([]() { std::cout << "world" << std::endl; });

  t1.join();
  t2.join();

  return 0;
}

在这个程序中,我们使用了std::thread类来创建新的线程,并使用join()函数来等待线程结束。由于C++11的多线程库包含了许多类和函数,所以可以支持多种多线程编程模型,比如生产者-消费者模型、同步-异步模型等等。

在C++11中,如果想要使用多线程库,需要在代码中包含<thread>头文件。这个头文件包含了所有多线程库的声明,并且提供了一些宏定义和常量,可以用来查询系统的多线程支持情况。

例如,可以使用std::thread::hardware_concurrency()函数来获取系统的最大线程数,或者使用std::this_thread::get_id()函数来获取当前线程的标识符,等等。

除了<thread>头文件之外,C++11的多线程库还包含了其他几个头文件,它们可以用来实现更为复杂的多线程程序。例如,<mutex>头文件包含了互斥量类型和函数,可以用来保证多个线程对共享数据的互斥访问;<future>头文件包含了futurepromise类型,可以用来实现线程间的同步和通信等等。

总之,C++11的多线程库为C++程序员提供了一系列的工具和类型,可以让他们编写高性能的多线程程序。

智能指针

智能指针是一种智能指针类型,它在管理内存时具有智能化的行为。普通的指针只能表示一个内存地址,而智能指针则具有自动释放内存和避免野指针等特性。

在C++11中,智能指针主要由两个模板类实现:std::unique_ptrstd::shared_ptr

std::unique_ptr表示一个独占的指针,它管理的内存在任何时候都只能被一个指针所指向。例如,当一个std::unique_ptr对象被析构时,它所管理的内存会被自动释放。 std::shared_ptr表示一个共享的指针,它管理的内存可以被多个指针所指向。例如,当一个std::shared_ptr对象的引用计数变为0时,它所管理的内存会被自动释放。 下面是一个使用std::unique_ptr的简单示例:

cpp
#include <iostream>
#include <memory>

int main() {
  std::unique_ptr<int> p(new int(5));  // 声明一个独占指针,并分配一个int类型的对象
  std::cout << *p << std::endl;  // 输出指针指向的对象的值

  return 0;
}

在这个程序中,我们声明了一个std::unique_ptr类型的指针p,并使用它来指向一个int类型的内存。我们可以通过解引用指针的方式来访问指针指向的对象,就像使用普通指针一样。当程序执行完毕,智能指针p会被析构,它所管理的内存就会被自动释放,避免了内存泄漏。

另一个模板类std::shared_ptr的用法也非常相似,下面是一个使用std::shared_ptr的简单示例:

cpp
#include <iostream>
#include <memory>

int main() {
  std::shared_ptr<int> p1(new int(5));  // 声明一个共享指针,并分配一个int类型的对象
  std::cout << *p1 << std::endl;  // 输出指针指向的对象的值

  std::shared_ptr<int> p2 = p1;  // 将一个共享指针赋值给另一个共享指针
  std::cout << p1.use_count() << " " << p2.use_count() << std::endl;  // 输出两个指针的引用计数

  return 0;
}

在这个程序中,我们声明了两个std::shared_ptr类型的指针p1和p2,并让它们指向同一个int类型的对象。我们可以通过调用指针的use_count()方法来获取它的引用计数,表示当前有多少个指针指向这个内存。当程序执行完毕,如果所有的指针都被析构了,智能指针所管理的内存就会被自动释放,避免了内存泄漏。

总之,智能指针是C++11中一个非常实用的类型,它可以自动管理内存的生命周期,减少程序员手动管理内存的工作量,并且可以避免常见的内存错误。

auto

自动类型推导

当与const结合使用时

  • 当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;
  • 当类型为引用时,auto 的推导结果将保留表达式的 const 属性。

auto的限制

  • 使用 auto 的时候必须对变量进行初始化

  • auto 不能在函数的参数中使用

    • 这个很容易理解,我们在定义函数的时候只是对参数进行了声明,指明了参数的类型,但并没有给它赋值,只有在实际调用函数的时候才会给参数赋值;而 auto 要求必须对变量进行初始化,所以这是矛盾的。
  • auto 不能作用于类的非静态成员变量(也就是没有 static 关键字修饰的成员变量)中

    • 可以用decltype定义,如下就可以写成decltype(T().begin()) m_it;
    cpp
    template <typename T>
    class A {
    private:
        typename T::iterator m_it;
    }
  • auto 关键字不能定义数组

  • auto 不能作用于模板参数

auto常用

  • 使用 auto 定义迭代器
  • auto 用于泛型编程

using

使用using定义别名(替代typedef

支持函数模板的默认模板参数

函数模板是C++中一种常见的技术,它允许定义一个函数,接受任意类型的参数。例如,下面是一个简单的函数模板示例:

cpp
#include <iostream>

template<typename T>
void print(T value) {
  std::cout << value << std::endl;
}

int main() {
  print(5);
  print("hello world");

  return 0;
}

在这个程序中,我们定义了一个名为print的函数模板,它接受一个模板参数T,表示函数接受任意类型的参数。在函数体内,我们可以像使用普通类型一样使用这个模板参数T。

C++11标准引入了一种新的语法,允许为函数模板定义默认模板参数。例如,下面是一个使用默认模板参数的函数模板示例:

cpp
#include <iostream>

template<typename T = int>
void print(T value) {
  std::cout << value << std::endl;
}

int main() {
  print(5);
  print("hello world");

  return 0;
}

在这个程序中,我们为函数模板print定义了一个默认模板参数T = int,表示如果调用函数时没有指定模板参数,就会使用默认的int类型作为模板参数。因此,在上面的程序中,调用函数print时,第一次调用会自动使用默认的模板参数int,并将实际参数5赋值给函数的形式参数value。

默认模板参数的作用是简化函数模板的调用,减少程序员的工作量。例如,我们可以通过使用默认模板参数,定义一个通用的排序函数,支持任意类型的数组排序,并且不需要显式地指定模板参数:

cpp
#include <algorithm>

template<typename T>
void sort(T* array, int size) {
  std::sort(array, array + size);
}

int main() {
  int array[] = {5, 3, 2, 4, 1};
  sort(array, 5);

  return 0;
}

在这个程序中,我们定义了一个名为sort的函数模板,它接受一个类型为T的数组和数组的长度作为参数。在函数体内,我们使用了C++标准库中的std::sort函数,将数组进行排序。因为我们没有为函数模板指定模板参数,所以编译器会自动推断出模板参数的类型,并使用默认的模板参数int进行编译。

总之,支持函数模板的默认模板参数是C++11标准的一项重要特性,它可以简化函数模板的定义和调用,提高程序的可读性和可维护性。

吃好喝好 快乐地活下去