C++11 | 从入门到放弃

熟悉C++的人知道,在经过了13年的漫长等待后,C++标准委员会终于在2011年通过了C++史上的第二个标准。

C++0x VS C++11,傻傻分不清楚

从一开始到现在,C++大概经历了以下几个比较重要的阶段:

  • 1998: ISO官方发布C++标准,俗称C++98,这是第一个C++的官方正式版本。

  • 2003: TC1(Technical Corrigendum 1)发布,俗称C++03, 这个版本可以当成是C++98的一个bugfix版本

  • 2005:TR1(Technical Report 1)发布,TR1是一个新增加的库,增加了大约14种新的组件到C++标准中

  • 2008:新C++标准(C++0x)草案发布,这个主要是以TR1的基础上进行了扩充

  • 2011:C++0x标准通过


随着各种动态解释型语言的诞生,C++程序员也越来越感觉到了C++语言本身的一些局限性。以C++之父 Bjarne Stroustrup (没错,就是下面这个仙风道骨的老头)为代表的先贤们,也一直在不遗余力的努力着,让C++更加强大。

于是他们商量着:

要么大伙每5年来一次华山论剑?

好!果真,后来的C++大会基本上是5年一次,比如 2003年,2008年。

1998年C++标准发布后,原计划于2003年之后的几年推出新的标准,但由于没有确定具体哪一年发布,就用 0x原来表示的是04-09年中的某一年。

等到了2009年,新的C++0x标准却一致拖着没通过,直到2011年才通过,名称还保持叫C++0x 对此,老头是这样解释的:

x表示是16进制的字符0-f,所以11也是x了。

所以说,C++0xC++11,这俩就是一回事,只不过前者是个草案,而后者是正式通过的标准。

thread

以前,由于 C++98中没有线程、锁、条件变量等这些与多线程相关的特性支持,如果需要写多线程程序,都要借助于不同平台上各自提供的 api,导致程序的跨平台移植性较差,经常要用一大堆的 #ifdef WIN32类似的宏来区分不同的平台,这样写代码的姿势很难看。

现在好了,使用 C++11 可以编写跨平台的多线程程序了,而且相比原来的 pthread写法,代码更简洁优美。

今天从 thread 开始,介绍下 C++11 带来的一系列新特性。

#include <iostream>
#include <string>
#include <thread>

using namespace std;

class Foo
{
public:
    void bar (int id, string& name) {
        name += "+1s";
        cout << "id=" << id << ",name=" << name << endl;
    }
};

void func ()
{
    cout << "thread func" << endl;
}

int main ()
{
    Foo foo;
    int id = 1;
    string name("elder");

    thread th_1 (func); //thread func
    th_1.join ();

    thread th_2 (&Foo::bar, foo, id, ref(name));//id=1,name=elder+1s
    th_2.join ();

    thread th_3 (bind (&Foo::bar, foo, id, name));//id=1,name=elder+1s+1s
    th_3.join ();

    thread th_4 ([&]{ foo.bar (id, name); });//id=1,name=elder+1s+1s
    th_4.join ();

    return 0;

上面是 thread 的四种构造方式:

(1) 最简单,最常用的方式,直接传入一个普通函数。

(2) 变参模版方式,如果函数为类的成员函数,第一个参数是对象本身,后面的参数按函数调用时的顺序传入。注意,引用传递参数的话实参用 ref(arg) 包装。

(3) bind 方式,传入一个 std::function对象,同样地,如果是类成员变量的话,第一个参数是对象本身。

(4) lambda 方式,是比较常用的方式(先留个坑,以后再细述)。

thread 对象

  • 不可被拷贝构造

  • 可以 `move` 方式构造,thread th(std::move(x)); 之后,新构造的 th 拥有原先 x 的执行对象,x 不再代表执行对象。

  • 可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detach

thread 方法

1.operator =

如果当前对象不可 joinable,将获取右值的执行对象,同时,右值将不再代表执行对象;
如果当前对象可被 joinable,则 terminate() 报错。

thread th;
th = thread(func); //√
th = th_1;         //x

2.get_id()

如果当前对象不可 joinable,返回默认构造线程的id(0x0)
如果当前对象可被 joinable,则返回当前线程的 id

3.joinable()

检测线程是否 joinable。当且仅当 thread 代表某个执行对象时,它才是 joinable的。下列条件下,属于 不可 joinable

a. 默认构造函数构造出来。对 thread th;而言,th 不代表任何 thread 执行对象。
b. 被作为参数给 std::move 调用。
c. 已经调用了 join 或 detach 函数。

4.swap(x)

交换当前线程和 x 的状态、执行对象等。

##  下集预告

关于 thread,必须掌握这些最最基本的姿势。下一篇,小明将撸一撸 C++11中多线程如何同步的问题。

来源:黄学忠-微信公众号

上一篇: C++指针的概念解读 超详细

下一篇: C++面试我一定会问的一个问题

分享到: 更多