c++11 thread

关于 c++11 的线程库,我们有如下几个问题:

  • 可否不传参数
  • 可否传递多个参数
  • 可否传递 const 参数
  • 可否传递引用参数
  • 可否传递 const 引用参数
  • std::thread 结构可否放入容器
  • std::thread 可否在类内部使用

针对以上问题,我们先来看一个标准的 c++11 线程库要怎么使用:

#include <stdio.h>
#include <thread>

void f(int a) {
    printf("%d\n", a);
}

int main() {
    printf("hello world\n");
    std::thread t(f, 1);
    t.join();
    return 0;
}
>g++ test_thread.cpp -std=c++11 -pthread && ./a.out
hello world
1

然后试了一下不传参数,是可以的;多个参数,也是可以的;const 参数也是可以的

当试到传引用的时候,需要这么写才可以

#include <stdio.h>
#include <thread>
#include <string>

void f(int a, std::string& b) {
    printf("%d\n%s\n", a, b.c_str());
    b = "456";
}

int main() {
    printf("hello world\n");
    std::string str = "123";
    std::thread t(f, 1, std::ref(str));
    t.join();
    printf("%s\n", str.c_str());
    return 0;
}
>g++ test_thread.cpp -std=c++11 -pthread && ./a.out
hello world
1
123
456

然后 const 引用也是可以的

容器中也可以放,但是取出的时候只能取出引用,而不能取出值

#include <stdio.h>
#include <thread>
#include <string>
#include <vector>

void f(int a, const std::string& b) {
    printf("%d\n%s\n", a, b.c_str());
}

int main() {
    printf("hello world\n");
    std::string str = "123";
    std::vector<std::thread> vecT;
    vecT.push_back(std::thread(f, 1, std::ref(str)));
    std::thread& t = vecT[0];
    t.join();
    printf("%s\n", str.c_str());
    return 0;
}
>g++ test_thread.cpp -std=c++11 -pthread && ./a.out
hello world
1
123
123

最后,在类中使用的话,像这么写的话

#include <stdio.h>
#include <thread>
#include <string>
#include <vector>

class TestClass {
public:
    void f(int a, const std::string& b) {
        printf("%d\n%s\n", a, b.c_str());
    }

    void r() {
        printf("hello world\n");
        std::string str = "123";
        std::vector<std::thread> vecT;
        vecT.push_back(std::thread(f, 1, std::ref(str)));
        std::thread& t = vecT[0];
        t.join();
        printf("%s\n", str.c_str());
    }
};

int main() {
    TestClass testClass;
    testClass.r();
    return 0;
}

是会报错的

>g++ test_thread.cpp -std=c++11 -pthread && ./a.out
test_thread.cpp: In member function ‘void TestClass::r()’:
test_thread.cpp:16:55: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, int, std::reference_wrapper<std::basic_string<char> >)’
         vecT.push_back(std::thread(f, 1, std::ref(str)));
                                                       ^
test_thread.cpp:16:55: note: candidates are:
In file included from test_thread.cpp:2:0:
/usr/local/include/c++/4.8.2/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (TestClass::*)(int, const std::basic_string<char>&); _Args = {int, std::reference_wrapper<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >}]
       thread(_Callable&& __f, _Args&&... __args)
       ^
/usr/local/include/c++/4.8.2/thread:133:7: note:   no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘void (TestClass::*&&)(int, const std::basic_string<char>&)’
/usr/local/include/c++/4.8.2/thread:128:5: note: std::thread::thread(std::thread&&)
     thread(thread&& __t) noexcept
     ^
/usr/local/include/c++/4.8.2/thread:128:5: note:   candidate expects 1 argument, 3 provided
/usr/local/include/c++/4.8.2/thread:122:5: note: std::thread::thread()
     thread() noexcept = default;
     ^
/usr/local/include/c++/4.8.2/thread:122:5: note:   candidate expects 0 arguments, 3 provided

搜了一下,看到 stackoverflow 上有人说, https://stackoverflow.com/ques…

The problem is that a member function can’t be called without an object. Provide a pointer to this so that the current object is used:

thread t(&ThreadClass::myThread, this, 10);
You could use an instance of any ThreadClass object, but in your case, it seems this is the right thing to do.

NOTE: Remember you need a reference to the created thread so that you can do a join() later on.

所以其实是类的成员函数中,隐含了第一个参数是一个 this 指针的原因

#include <stdio.h>
#include <thread>
#include <string>
#include <vector>

class TestClass {
public:
    void f(int a, const std::string& b) {
        printf("%d\n%s\n", a, b.c_str());
    }

    void r() {
        printf("hello world\n");
        std::string str = "123";
        std::vector<std::thread> vecT;
        vecT.push_back(std::thread(&TestClass::f, this, 1, std::ref(str)));
        std::thread& t = vecT[0];
        t.join();
        printf("%s\n", str.c_str());
    }
};

int main() {
    TestClass testClass;
    testClass.r();
    return 0;
}

改写成这样,就可以了

>g++ test_thread.cpp -std=c++11 -pthread && ./a.out
hello world
1
123
123

那很自然的,会接着一个问题,就是这个 f 能否是一个私有函数呢

试了一下,会发现,答案是可以的

Leave a Reply

Your email address will not be published. Required fields are marked *