【问题标题】:Visual Studio 2013 std::threadVisual Studio 2013 标准::线程
【发布时间】:2015-03-02 07:09:29
【问题描述】:

以下程序在使用 Visual Studio 2013 编译时会出现一些奇怪的编译/运行时行为:

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <iostream>

int main()
{

    {//works
        std::thread([](){
            std::cout << " thread running1\n";
        });
    }

    {//compile but synstax error exist
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread(fun); //fun is not defined
    }


    {//compile, see next block for mystery compile error
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread tmp(func); 
    }

    {//does not compile and don't know why
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread(func); //error C2371: 'func' : redefinition; different basic types
    }

    return 0;
}

当这个程序工作时,可能会因为线程之间存在竞争条件而崩溃。主线程可能在其他线程之前结束。

有人知道为什么第二个块和最后一个块不起作用吗?

【问题讨论】:

    标签: c++ multithreading c++11 visual-studio-2013 stdthread


    【解决方案1】:
    {//compile but synstax error exist
        auto func = [](){
            std::cout << " thread running2\n";
        };
    
        std::thread(fun); //fun is not defined
    }
    

    这里没有语法错误,std::thread(fun) 默认构造了一个名为funstd::thread 对象。

    最后一个block的错误是因为同样的原因

    std::thread(func); //error C2371: 'func' : redefinition; different basic types
    

    您正在尝试默认构造一个名为 funcstd::thread 对象,这是一个错误,因为同名的 lambda 已存在于同一范围内。要将 lambda 传递给 thread 构造函数,请改用大括号

     std::thread{func};
    

    现在,在您进行这些更改后,您的代码将编译但将在运行时失败,因为块 1、3 和 4 中的线程对象都将调用 std::terminate(当然,您的程序在第一个线程对象调用std::terminate,所以其他两个这样做是有争议的)。

    发生这种情况的原因是您在所有 3 个块中都有 可连接 线程,并且如果此类线程对象的 destructor 运行,std::terminate will be called。为避免这种情况,您必须致电thread::join(您也可以致电thread::detach,但不要这样做)。

    例如

    {//works
        std::thread([](){
            std::cout << " thread running1\n";
        }).join();
    }
    

    Live demo

    【讨论】:

    • c++ 中的语法在哪里发生了变化?我的理解是 std::thread(func);将创建一个未命名的对象,将 func 传递给构造函数。 Ps 我的程序现在可以工作了:-)
    • @Johan 一直都是这样。见this answer;如果你愿意,你可以添加更多的括号对:)
    猜你喜欢
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多