【问题标题】:vector of std::threadsstd::threads 的向量
【发布时间】:2013-03-16 17:00:11
【问题描述】:

C++11

我正在尝试制作std::threads 中的vector。结合以下三点说我可以。

1.) 根据http://en.cppreference.com/w/cpp/thread/thread/threadthread 的默认构造函数创建一个

不代表线程的线程对象。

2.) 根据http://en.cppreference.com/w/cpp/thread/thread/operator%3D, threadoperator=

分配[参数的状态,其中 是使用 move 对 [调用线程] 的线程右值引用] 语义。

3.) 根据 http://en.cppreference.com/w/cpp/container/vector/vector,通过 只有向量构造函数的大小类型变量会构造

具有[指定数量]值初始化的容器(默认构造,对于 classes) T 的实例。不复制。

所以,我这样做了:

#include <iostream>
#include <thread>
#include <vector>

void foo()
{
    std::cout << "Hello\n";
    return;
}

int main()
{
    std::vector<std::thread> vecThread(1);
    vecThread.at(0) = std::thread(foo);
    vecThread.at(0).join();
    return 0;
}

这在 VC11 和 g++ 4.8.0 (online compiler here) 中按预期运行,如下所示:

控制台输出:

Hello

然后我在 clang 3.2 中进行了尝试,通过在同一网页上切换编译器菜单,得到:

stderr: 
pure virtual method called
terminate called without an active exception

当代表线程的线程对象在join()ed 或detach()ed 之前超出范围时,程序将被强制终止。我有join()ed vecThread.at(0),所以唯一剩下的就是临时线程

std::thread(foo);

vecThread.at(0) = std::thread(foo);

任务。

然而,根据网络参考,线程只能通过移动线程右值引用来分配。我想不出任何办法来join()detach() 临时线程对象。

那么如果clang的输出是正确的,那么threadoperator=有什么用呢?或者这是一个clang编译器错误?

在 g++ 4.8.0 中,换行

vecThread.at(0) = std::thread(foo)

vecThread.at(0) = std::thread{foo}

(用大括号替换圆括号)仍然给出预期的Hello 输出。

但是,将行更改为 vecThread.at(0) = {foo} 会使其抱怨:

g++ 4.8.0 对大括号的抱怨:

错误:从初始化列表转换为 'std::thread' 将使用 显式构造函数 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(); _Args = {}]' vecThread.at(0) = {foo};

太高级了——我不知道是什么意思。

在 clang 中进行相同的更改可以提供更高级的功能:

clang 3.2 对大括号的抱怨:

error: no viable overloaded '='
vecThread.at(0) = {foo};
...
note: candidate function not viable: cannot convert initializer list
argument to 'const std::thread'
thread& operator=(const thread&) = delete;
...
note: candidate function not viable: cannot convert initializer list
argument to 'std::thread'
thread& operator=(thread&& __t) noexcept

我也不知道这意味着什么。

我不能用VC11来证实上述情况

vecThread.at(0) = {foo}

问题是因为 VC11,截至 2012 年 11 月的 CTP 编译器,不支持标准库上的统一初始化语法。

【问题讨论】:

  • 你是用-pthread编译的吗?代码看起来不错,虽然有点冗长。
  • 您的意思是我应该将–pthread 添加到在线编译器的compiler/interpreter 参数文本字段中吗?我将它添加到网页的文本字段的原始编译器/解释器参数中,使其在 clang 上为 -std=c++11 -Wall -W -pedantic -O2 –pthread,但在调用 terminate 时得到了相同的结果。
  • 好吧,this code 在使用 -std=c++0x -pthread 编译时对我有用...
  • 我为名为@9​​87654357@ 的liveworkspace 写了一个小sn-p。玩它而不是 std::thread
  • AFAIK,当您使用标志 -stdlib=libstdc++ 编译时会引发此异常。这是众所周知的bug。有些人建议使用 llvm c++ 库,但我现在无法确认。你可以检查一下,如果你已经安装了这个库(在编译器参数中添加-stdlib=libc++)。

标签: c++ multithreading vector c++11 stdthread


【解决方案1】:

你的第一个例子是正确的。当您将 clang 与 libstdc++ 一起使用时,抛出异常是已知的 bug。要解决它,您必须安装 libc++(llvm 版本的 c++ 库)。请看下面使用 libc++ 编译的示例

#include <thread>

int main()
{
    std::thread t([] () {});
    t.join();
    return 0;
}

$ clang++ -std=c++11 -stdlib=libc++ main.cpp -o main -lc++ -lsupc++ -lpthread

附:见here,为什么-lsupc++也需要标志。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    相关资源
    最近更新 更多