2015-03-02 2 views
2

следующая программа даст какое-то странное поведение компиляции/времени выполнения при компиляции с Visual Studio 2013: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; 
} 

Когда эта программа работы, там может произойти сбой, как есть состояние гонки между нить. Основной поток может заканчиваться перед другими потоками.

Кто-нибудь знает, почему второй блок и последний блок не работают?

ответ

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

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

Там нет синтаксических ошибок здесь, std::thread(fun) по умолчанию строит std::thread объект с именем fun.

Ошибка в последнем блоке из-за той же самой причине

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

Вы пытаетесь по умолчанию построить std::thread объект с именем func выше, и это ошибка, потому что лямбда с тем же именем уже существует в тот же объем. Для того, чтобы передать лямбда, чтобы использовать 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

+0

Где синтаксис изменился в C++? Я понял, что std :: thread (func); создаст неназванный объект, передающий func конструктору. Ps моя программа работает сейчас :-) – Johan

+0

@Johan Это всегда было так. См. [Этот ответ] (http://stackoverflow.com/a/6342009/241631); вы можете добавить еще больше пар круглых скобок, если хотите :) – Praetorian

Смежные вопросы