代码之家  ›  专栏  ›  技术社区  ›  Swiss Frank

C++向量<thread*>push_back():无法找到创建未命名线程变量的咒语

  •  0
  • Swiss Frank  · 技术社区  · 5 年前

    创建一个命名线程对我来说很有效:

    void inserter( int iTimes ) {
      for ( int i = 0; i < iTimes; i++ )
          DoOne();
    }
    
    int main( int nArg, const char* apszArg[] ) {
      std::thread t1( inserter, 100 );
          :
          :
    

    但我不知道在创建没有名称的线程时该怎么做。这会产生一个无法解析构造函数的错误。我还想知道,一旦这种方法奏效,向量的类型是否正确,或者是否 thread* 我需要指定模板参数,如果是这样,如何为1)函数和2)参数列表指定模板参数。

    using namespace std;
    vector<thread*> apthread;
    
    for ( int i = 0; i < nThreads; i++ )
        apthread.push_back( new thread( inserter, i ) );
    
    0 回复  |  直到 5 年前
        1
  •  4
  •   Anthony Williams    5 年前

    示例代码中唯一明确缺少的使其编译的东西是 std:: : https://godbolt.org/z/3gX_h2

    #include <thread>
    #include <vector>
    
    void DoOne(){}
    
    void DoMany( int iTimes ) {
        for ( int i = 0; i < iTimes; i++ )
            DoOne();
    }
    
    int main(){
        std::vector<std::thread*> apthread;
    
        const auto nThreads=10;
    
        for ( int i = 0; i < nThreads; i++ )
            apthread.push_back( new std::thread( DoMany, i ) ); 
    
        // join all the threads
        for(auto& t: apthread){
            t->join();
        }
    
    }
    

    但是,你永远不应该使用plain new ,并且不需要使用动态分配 std::thread 不管怎样:它已经是一个句柄,你可以 push_back 将新线程对象放入向量中:

    #include <thread>
    #include <vector>
    
    void DoOne(){}
    
    void DoMany( int iTimes ) {
        for ( int i = 0; i < iTimes; i++ )
            DoOne();
    }
    
    int main(){
        std::vector<std::thread> apthread;
    
        const auto nThreads=10;
    
        for ( int i = 0; i < nThreads; i++ )
            apthread.push_back(std::thread( DoMany, i ) );    
    
        // join all the threads
        for(auto& t: apthread){
            t.join();
        }
    }
    
        2
  •  0
  •   Swiss Frank    5 年前

    问题不是由于线程向量造成的。

    相反,问题在于线程函数被调用 inserter() ,它也是C++标准库定义的符号。

    矢量版本除了添加矢量外,还添加了 using namespace std; 这阻止了编译器(g++7.2.1)解析意图。

    将函数名更改为几乎任何其他名称(未由标准库定义)都可以进行编译。同样,删除 使用命名空间std; 而是明确地在所有库符号前添加 std:: 作品。